From: Cheng-Shiun Tsai Date: Fri, 2 Oct 2020 09:47:01 +0000 (+0100) Subject: [dali_1.9.32] Merge branch 'devel/master' X-Git-Tag: dali_2.0.2~1^2~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=24cf3ec005ffb58f751fe8f1ff41beb52128917d;hp=454a2ddbed8d022e32a31dcd225a7ac32903b282;p=platform%2Fcore%2Fuifw%2Fdali-core.git [dali_1.9.32] Merge branch 'devel/master' Change-Id: I273fcca7812387ae4d62a455aa69c43ea8f95c9f --- diff --git a/automated-tests/src/dali/utc-Dali-PropertyValue.cpp b/automated-tests/src/dali/utc-Dali-PropertyValue.cpp index 762e99a..a3f8292 100644 --- a/automated-tests/src/dali/utc-Dali-PropertyValue.cpp +++ b/automated-tests/src/dali/utc-Dali-PropertyValue.cpp @@ -478,6 +478,29 @@ int UtcDaliPropertyValueCopyConstructorStringP(void) END_TEST; } +int UtcDaliPropertyValueCopyAssignStringDifferentTypeP(void) +{ + Property::Value value1{Vector4(3.f, 2.f, 1.f, 2.0f)}; + Property::Value value2{"very very long string ..................."}; + value2 = value1; + + Vector4 vec1, vec2; + value1.Get(vec1); + value2.Get(vec2); + DALI_TEST_EQUALS(value1.GetType(), value2.GetType(), TEST_LOCATION); + DALI_TEST_EQUALS(vec1, vec2, TEST_LOCATION); + + Property::Value value3{Vector4(3.f, 2.f, 1.f, 2.0f)}; + Property::Value value4{"very very long string ..................."}; + + value3 = value4; + + DALI_TEST_EQUALS(value3.GetType(), value4.GetType(), TEST_LOCATION); + DALI_TEST_EQUALS(value3.Get(), "very very long string ...................", TEST_LOCATION); + DALI_TEST_EQUALS(value3.Get(), value4.Get(), TEST_LOCATION); + END_TEST; +} + int UtcDaliPropertyValueCopyConstructorArrayP(void) { Property::Value value1(Property::ARRAY); diff --git a/dali/internal/event/common/demangler-unix.cpp b/dali/internal/event/common/demangler-unix.cpp index 07a63a1..773b653 100644 --- a/dali/internal/event/common/demangler-unix.cpp +++ b/dali/internal/event/common/demangler-unix.cpp @@ -15,38 +15,27 @@ * */ +// EXTERNAL HEADER +#include + // FILE HEADER #include -// INTERNAL HEADERS -#include - namespace { - -// true if character represent a digit -inline bool IsDigit(char c) -{ - return (c >= '0' && c <= '9'); -} - -// Gets the number of characters (number is in string) -// start The start position to look for a number -// result The number as an integer -// returns the number of characters used to define the number ie '12' is 2 -size_t GetNumberOfCharacters(const std::string& s, const size_t& start, int& result) +// Extracts the number from the src view and update the view. +size_t ExtractNumber(std::string_view& src) { - size_t size = s.size(); - - size_t i = start; - - int number = 0; + auto IsDigit = [](char c) { return (c >= '0' && c <= '9'); }; + size_t number = 0; - for( ; i < size; ++i ) + for(auto i = 0u; i < src.size(); ++i) { - char c = s.at(i); + char c = src[i]; if( !IsDigit( c ) ) { + //update the src view. + src.remove_prefix(i); break; } else @@ -55,53 +44,41 @@ size_t GetNumberOfCharacters(const std::string& s, const size_t& start, int& res } } - if( i - start ) - { - result = number; - } - - return i - start; + return number; } /** - * @brief Demangle a nested typeid name into its component parts. + * @brief Demangle a nested typeid name into its component parts and return + * the last component. * A nested type name is one containing namespaces and class names only. - * eg DemangleNestedNames(typeid(Dali::Actor).name()); + * eg ExtractDemangleNestedName(typeid(Dali::Actor).name()); * @param[in] typeIdName The type id name string to demangle. - * @returns the demangled list of names ie ["Dali","Actor"] or an empty list + * @returns the last component "Actor" or an empty string_view */ -std::vector DemangleNestedNames(const char *typeIdName) +std::string_view ExtractDemangleNestedName(std::string_view mangledName) { - // Demangle class name mangled according to the Itanium C++ ABI - // Returns demangled names ie "N4Dali8Internal5ActorE" is ["Dali","Internal","Actor"] - std::vector ret; - - const std::string mangledName(typeIdName); - - - size_t size = mangledName.size(); - - if( size >= 2 ) + if(mangledName.empty()) { - int number = 0; - size_t start = 0; - - // If the class isnt nested in a namespace then it just starts with the - // number of characters - if(mangledName[0] == 'N' && mangledName[size-1] == 'E') - { - start = 1; - } + return {}; + } - while( size_t chars = GetNumberOfCharacters(mangledName, start, number) ) - { - ret.push_back( mangledName.substr( start + chars, number ) ); + // classes nested inside a namespace starts with 'N' and ends with 'E' + // so trim those + if(mangledName.front() == 'N' && mangledName.back() == 'E') + { + mangledName.remove_prefix(1); + mangledName.remove_suffix(1); + } - start += chars + number; - } + std::string_view result; + while(!mangledName.empty()) + { + auto length = ExtractNumber(mangledName); + result = {mangledName.data(), length}; + mangledName.remove_prefix(length); } - return ret; + return result; } } // anon namespace @@ -111,18 +88,9 @@ namespace Dali namespace Internal { - -const std::string DemangleClassName(const char *typeIdName) +std::string DemangleClassName(const char* typeIdName) { - std::string name; - std::vector names = DemangleNestedNames(typeIdName); - - if( names.size() ) - { - name = names[ names.size() - 1 ]; - } - - return name; + return std::string(ExtractDemangleNestedName(typeIdName)); } } // namespace Internal diff --git a/dali/internal/event/common/demangler-windows.cpp b/dali/internal/event/common/demangler-windows.cpp index 9d6612a..cdfc58b 100644 --- a/dali/internal/event/common/demangler-windows.cpp +++ b/dali/internal/event/common/demangler-windows.cpp @@ -23,8 +23,7 @@ namespace Dali namespace Internal { - -const std::string DemangleClassName(const char *typeIdName) +std::string DemangleClassName(const char* typeIdName) { std::string name = typeIdName; int index = name.find_last_of(' '); diff --git a/dali/internal/event/common/demangler.h b/dali/internal/event/common/demangler.h index 4d9790b..647e015 100644 --- a/dali/internal/event/common/demangler.h +++ b/dali/internal/event/common/demangler.h @@ -32,7 +32,7 @@ namespace Internal * @param[in] typeIdName The type id name string to demangle. * @returns the class name ie "Actor" or an empty string */ -const std::string DemangleClassName(const char *typeIdName); +std::string DemangleClassName(const char* typeIdName); } // namespace Internal diff --git a/dali/internal/event/common/property-metadata.cpp b/dali/internal/event/common/property-metadata.cpp index aa4d607..1df9d5e 100644 --- a/dali/internal/event/common/property-metadata.cpp +++ b/dali/internal/event/common/property-metadata.cpp @@ -86,7 +86,7 @@ void PropertyMetadata::SetPropertyValue( const Property::Value& propertyValue ) case Property::ARRAY: { - Property::Array* array = propertyValue.GetArray(); + const Property::Array* array = propertyValue.GetArray(); if( array ) { value = *array; @@ -96,7 +96,7 @@ void PropertyMetadata::SetPropertyValue( const Property::Value& propertyValue ) case Property::MAP: { - Property::Map* map = propertyValue.GetMap(); + const Property::Map* map = propertyValue.GetMap(); if( map ) { value = *map; diff --git a/dali/internal/event/common/scene-impl.cpp b/dali/internal/event/common/scene-impl.cpp old mode 100644 new mode 100755 index 7f85aa1..496fba4 --- a/dali/internal/event/common/scene-impl.cpp +++ b/dali/internal/event/common/scene-impl.cpp @@ -375,6 +375,11 @@ Integration::Scene::WheelEventSignalType& Scene::WheelEventSignal() return mWheelEventSignal; } +std::vector& Scene::GetItemsDirtyRects() +{ + return mItemsDirtyRects; +} + } // Internal } // Dali diff --git a/dali/internal/event/common/scene-impl.h b/dali/internal/event/common/scene-impl.h old mode 100644 new mode 100755 index 96b8a8f..67d08d5 --- a/dali/internal/event/common/scene-impl.h +++ b/dali/internal/event/common/scene-impl.h @@ -44,6 +44,54 @@ namespace Internal namespace SceneGraph { class Scene; + +struct DirtyRect +{ + DirtyRect(Node* node, Render::Renderer* renderer, int frame, Rect& rect) + : node(node), + renderer(renderer), + frame(frame), + rect(rect), + visited(true) + { + } + + DirtyRect() + : node(nullptr), + renderer(nullptr), + frame(0), + rect(), + visited(true) + { + } + + bool operator<(const DirtyRect& rhs) const + { + if (node == rhs.node) + { + if (renderer == rhs.renderer) + { + return frame > rhs.frame; // Most recent rects come first + } + else + { + return renderer < rhs.renderer; + } + } + else + { + return node < rhs.node; + } + } + + Node* node; + Render::Renderer* renderer; + int frame; + + Rect rect; + bool visited; +}; + } class EventProcessor; @@ -260,6 +308,13 @@ public: */ Integration::Scene::WheelEventSignalType& WheelEventSignal(); + /** + * @brief Get ItemsDirtyRects + * + * @return the ItemsDirtyRects + */ + std::vector& GetItemsDirtyRects(); + public: /** @@ -327,6 +382,8 @@ private: // The wheel event signal Integration::Scene::WheelEventSignalType mWheelEventSignal; + + std::vector mItemsDirtyRects; }; } // Internal diff --git a/dali/internal/event/rendering/shader-impl.cpp b/dali/internal/event/rendering/shader-impl.cpp index 1a7f11f..3c3dcf9 100644 --- a/dali/internal/event/rendering/shader-impl.cpp +++ b/dali/internal/event/rendering/shader-impl.cpp @@ -124,7 +124,7 @@ void Shader::SetDefaultProperty( Property::Index index, const Property::Value& p { if( propertyValue.GetType() == Property::MAP ) { - Dali::Property::Map* map = propertyValue.GetMap(); + const Dali::Property::Map* map = propertyValue.GetMap(); if( map ) { std::string vertex; diff --git a/dali/internal/render/common/render-algorithms.cpp b/dali/internal/render/common/render-algorithms.cpp old mode 100644 new mode 100755 index 744ae86..f5d540c --- a/dali/internal/render/common/render-algorithms.cpp +++ b/dali/internal/render/common/render-algorithms.cpp @@ -418,6 +418,7 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList, if (!rootClippingRect.IsEmpty()) { context.SetScissorTest( true ); + context.Scissor( rootClippingRect.x, rootClippingRect.y, rootClippingRect.width, rootClippingRect.height ); mScissorStack.push_back( rootClippingRect ); } // We are not performing a layer clip and no clipping rect set. Add the viewport as the root scissor rectangle. diff --git a/dali/internal/render/common/render-item.cpp b/dali/internal/render/common/render-item.cpp old mode 100644 new mode 100755 index b795530..d0daa83 --- a/dali/internal/render/common/render-item.cpp +++ b/dali/internal/render/common/render-item.cpp @@ -110,8 +110,8 @@ ClippingBox RenderItem::CalculateViewportSpaceAABB( const Vector3& size, const i static_cast( viewportWidth ) * 0.5f - aabb.x, static_cast( viewportHeight ) * 0.5f - aabb.y ); - int x = static_cast< int >( roundf( aabbInScreen.x ) ); - int y = static_cast< int >( roundf( aabbInScreen.y ) ); + int x = static_cast< int >( floor( aabbInScreen.x ) ); + int y = static_cast< int >( floor( aabbInScreen.y ) ); int z = static_cast< int >( roundf( aabbInScreen.z ) ); int w = static_cast< int >( roundf( aabbInScreen.w ) ); diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp old mode 100644 new mode 100755 index d3db8f3..e885c33 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.cpp @@ -48,53 +48,6 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_REN } // unnamed namespace #endif -struct DirtyRect -{ - DirtyRect(Node* node, Render::Renderer* renderer, int frame, Rect& rect) - : node(node), - renderer(renderer), - frame(frame), - rect(rect), - visited(true) - { - } - - DirtyRect() - : node(nullptr), - renderer(nullptr), - frame(0), - rect(), - visited(true) - { - } - - bool operator<(const DirtyRect& rhs) const - { - if (node == rhs.node) - { - if (renderer == rhs.renderer) - { - return frame > rhs.frame; // Most recent rects come first - } - else - { - return renderer < rhs.renderer; - } - } - else - { - return node < rhs.node; - } - } - - Node* node; - Render::Renderer* renderer; - int frame; - - Rect rect; - bool visited; -}; - /** * Structure to contain internal data */ @@ -124,8 +77,7 @@ struct RenderManager::Impl programController( glAbstraction ), depthBufferAvailable( depthBufferAvailableParam ), stencilBufferAvailable( stencilBufferAvailableParam ), - partialUpdateAvailable( partialUpdateAvailableParam ), - itemsCheckSum(0) + partialUpdateAvailable( partialUpdateAvailableParam ) { // Create thread pool with just one thread ( there may be a need to create more threads in the future ). threadPool = std::unique_ptr( new Dali::ThreadPool() ); @@ -222,8 +174,6 @@ struct RenderManager::Impl std::unique_ptr threadPool; ///< The thread pool Vector boundTextures; ///< The textures bound for rendering Vector textureDependencyList; ///< The dependency list of binded textures - std::size_t itemsCheckSum; ///< The damaged render items checksum from previous prerender phase. - std::vector itemsDirtyRects; }; RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction, @@ -648,15 +598,19 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector> // Clean collected dirty/damaged rects on exit if 3d layer or 3d node or other conditions. DamagedRectsCleaner damagedRectCleaner(damagedRects); + + + Internal::Scene& sceneInternal = GetImplementation(scene); + SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject(); + // Mark previous dirty rects in the sorted array. The array is already sorted by node and renderer, frame number. - // so you don't need to sort: std::stable_sort(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end()); - for (DirtyRect& dirtyRect : mImpl->itemsDirtyRects) + // so you don't need to sort: std::stable_sort(itemsDirtyRects.begin(), itemsDirtyRects.end()); + std::vector& itemsDirtyRects = sceneInternal.GetItemsDirtyRects(); + for (DirtyRect& dirtyRect : itemsDirtyRects) { dirtyRect.visited = false; } - Internal::Scene& sceneInternal = GetImplementation(scene); - SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject(); uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex ); for (uint32_t i = 0; i < count; ++i) { @@ -759,11 +713,11 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector> // 2. Mark the related dirty rects as visited so they will not be removed below. // 3. Keep only last 3 dirty rects for the same node and renderer (Tizen uses 3 back buffers, Ubuntu 1). dirtyRect.rect = rect; - auto dirtyRectPos = std::lower_bound(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end(), dirtyRect); - dirtyRectPos = mImpl->itemsDirtyRects.insert(dirtyRectPos, dirtyRect); + auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect); + dirtyRectPos = itemsDirtyRects.insert(dirtyRectPos, dirtyRect); int c = 1; - while (++dirtyRectPos != mImpl->itemsDirtyRects.end()) + while (++dirtyRectPos != itemsDirtyRects.end()) { if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer) { @@ -777,7 +731,7 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector> c++; if (c > 3) // no more then 3 previous rects { - mImpl->itemsDirtyRects.erase(dirtyRectPos); + itemsDirtyRects.erase(dirtyRectPos); break; } } @@ -789,8 +743,8 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector> { // 1. The item is not dirty, the node and renderer referenced by the item are still exist. // 2. Mark the related dirty rects as visited so they will not be removed below. - auto dirtyRectPos = std::lower_bound(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end(), dirtyRect); - while (dirtyRectPos != mImpl->itemsDirtyRects.end()) + auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect); + while (dirtyRectPos != itemsDirtyRects.end()) { if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer) { @@ -808,9 +762,9 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector> } // Check removed nodes or removed renderers dirty rects - auto i = mImpl->itemsDirtyRects.begin(); - auto j = mImpl->itemsDirtyRects.begin(); - while (i != mImpl->itemsDirtyRects.end()) + auto i = itemsDirtyRects.begin(); + auto j = itemsDirtyRects.begin(); + while (i != itemsDirtyRects.end()) { if (i->visited) { @@ -824,7 +778,7 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector> i++; } - mImpl->itemsDirtyRects.resize(j - mImpl->itemsDirtyRects.begin()); + itemsDirtyRects.resize(j - itemsDirtyRects.begin()); damagedRectCleaner.SetCleanOnReturn(false); } diff --git a/dali/public-api/actors/custom-actor-impl.h b/dali/public-api/actors/custom-actor-impl.h index 11bb9e4..3afaa88 100644 --- a/dali/public-api/actors/custom-actor-impl.h +++ b/dali/public-api/actors/custom-actor-impl.h @@ -288,6 +288,9 @@ protected: // For derived classes { ACTOR_BEHAVIOUR_DEFAULT = 0, ///< Use to provide default behaviour (size negotiation is on, event callbacks are not called). @SINCE_1_2_10 DISABLE_SIZE_NEGOTIATION = 1 << 0, ///< True if control does not need size negotiation, i.e. it can be skipped in the algorithm @SINCE_1_0.0 + NOT_IN_USE_1 = 1<<1, + NOT_IN_USE_2 = 1<<2, + NOT_IN_USE_3 = 1<<3, LAST_ACTOR_FLAG ///< Special marker for last actor flag @SINCE_1_0.0 }; diff --git a/dali/public-api/dali-core-version.cpp b/dali/public-api/dali-core-version.cpp index 5d2c491..7ee6ca0 100644 --- a/dali/public-api/dali-core-version.cpp +++ b/dali/public-api/dali-core-version.cpp @@ -27,7 +27,7 @@ namespace Dali { const uint32_t CORE_MAJOR_VERSION = 1; const uint32_t CORE_MINOR_VERSION = 9; -const uint32_t CORE_MICRO_VERSION = 31; +const uint32_t CORE_MICRO_VERSION = 32; const char* const CORE_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/dali/public-api/object/property-value.cpp b/dali/public-api/object/property-value.cpp index 6c80133..09bb5c7 100644 --- a/dali/public-api/object/property-value.cpp +++ b/dali/public-api/object/property-value.cpp @@ -39,230 +39,489 @@ 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); -} -} // namespace 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() + { + static_assert(sizeof(Impl) == 16); + static_assert(alignof(Impl) == alignof(Impl*)); + + SetType(Property::NONE); + } + Impl(bool booleanValue) - : type(Property::BOOLEAN), - integerValue(booleanValue) { + SetType(Property::BOOLEAN); + mData.mBool.member = booleanValue; } Impl(float floatValue) - : type(Property::FLOAT), - floatValue(floatValue) { + SetType(Property::FLOAT); + mData.mFloat.member = floatValue; } Impl(int32_t integerValue) - : type(Property::INTEGER), - integerValue(integerValue) { + SetType(Property::INTEGER); + mData.mInt.member = integerValue; } - Impl(const Vector2& vectorValue) - : type(Property::VECTOR2), - vector2Value(new Vector2(vectorValue)) + Impl(Vector2 vectorValue) { + SetType(Property::VECTOR2); + ConstructInplace(mData.mVector2.member, std::move(vectorValue)); } - Impl(const Vector3& vectorValue) - : type(Property::VECTOR3), - vector3Value(new Vector3(vectorValue)) + Impl(Vector3 vectorValue) { + SetType(Property::VECTOR3); + ConstructInplace(mData.mVector3.member, std::move(vectorValue)); } - Impl(const Vector4& vectorValue) - : type(Property::VECTOR4), - vector4Value(new Vector4(vectorValue)) + Impl(Extents extentsValue) { + SetType(Property::EXTENTS); + ConstructInplace(mData.mExtents.member, std::move(extentsValue)); } - Impl(const Matrix3& matrixValue) - : type(Property::MATRIX3), - matrix3Value(new Matrix3(matrixValue)) + Impl(Property::Map mapValue) { + SetType(Property::MAP); + ConstructInplace(mData.mMap.member, std::move(mapValue)); } - Impl(const Matrix& matrixValue) - : type(Property::MATRIX), - matrixValue(new Matrix(matrixValue)) + Impl(Property::Array arrayValue) { + SetType(Property::ARRAY); + ConstructInplace(mData.mArray.member, std::move(arrayValue)); } - Impl(const AngleAxis& angleAxisValue) - : type(Property::ROTATION), - angleAxisValue(new AngleAxis(angleAxisValue)) + Impl(std::string stringValue) { + SetType(Property::STRING); + mData.mString.member = new std::string(std::move(stringValue)); } - Impl(const Quaternion& quaternionValue) - : type(Property::ROTATION), - angleAxisValue(new AngleAxis()) + Impl(Rect rectValue) { - quaternionValue.ToAxisAngle(angleAxisValue->axis, angleAxisValue->angle); + SetType(Property::RECTANGLE); + mData.mRect.member = new Rect(std::move(rectValue)); } - Impl(const std::string& stringValue) - : type(Property::STRING), - stringValue(new std::string(stringValue)) + Impl(Vector4 vectorValue) { + SetType(Property::VECTOR4); + mData.mVector4.member = new Vector4(std::move(vectorValue)); } - Impl(const Rect& rectValue) - : type(Property::RECTANGLE), - rectValue(new Rect(rectValue)) + Impl(Matrix3 matrixValue) { + SetType(Property::MATRIX3); + mData.mMatrix3.member = new Matrix3(std::move(matrixValue)); } - Impl(const Rect& rectValue) - : type(Property::VECTOR4), - vector4Value(new Vector4(rectValue.x, rectValue.y, rectValue.width, rectValue.height)) + Impl(Matrix matrixValue) { + SetType(Property::MATRIX); + mData.mMatrix.member = new Matrix(std::move(matrixValue)); } - Impl(const Property::Array& arrayValue) - : type(Property::ARRAY), - arrayValue(new Property::Array(arrayValue)) + Impl(AngleAxis angleAxisValue) { + SetType(Property::ROTATION); + mData.mAngleAxis.member = new AngleAxis(std::move(angleAxisValue)); } - Impl(Property::Array&& arrayValue) - : type(Property::ARRAY), - arrayValue(new Property::Array(std::move(arrayValue))) + Type GetType() const { + return mData.mType.type; } - Impl(const Property::Map& mapValue) - : type(Property::MAP), - mapValue(new Property::Map(mapValue)) + bool GetBool() const { + return mData.mBool.member; } - Impl(Property::Map&& mapValue) - : type(Property::MAP), - mapValue(new Property::Map(std::move(mapValue))) + int32_t GetInt() const { + return mData.mInt.member; } - Impl(const Extents& extentsValue) - : type(Property::EXTENTS), - extentsValue(new Extents(extentsValue)) + float GetFloat() const { + return mData.mFloat.member; } - Impl(const std::initializer_list& values) - : type(Property::MAP), - mapValue(new Property::Map(values)) + const Extents& GetExtents() const { + return mData.mExtents.member; } - /** - * Destructor, takes care of releasing the dynamically allocated types - */ - ~Impl() + 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() { - switch(type) + 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: // FALLTHROUGH - case Property::BOOLEAN: // FALLTHROUGH - case Property::FLOAT: // FALLTHROUGH + 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: { - break; // nothing to do + mData.mInt.member = other.GetInt(); + break; + } + case Property::EXTENTS: + { + auto obj = other.GetExtents(); + ConstructInplace(mData.mExtents.member, std::move(obj)); + break; } case Property::VECTOR2: { - delete vector2Value; + 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 + { + 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 { - 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; + Data() + { + } + ~Data() + { + } + + 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; }; -private: - // non-copyable - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; + Data mData; }; Property::Value::Value() @@ -316,7 +575,7 @@ Property::Value::Value(const Rect& rectValue) } Property::Value::Value(const Rect& rectValue) -: mImpl(new Impl(rectValue)) +: mImpl(new Impl(Vector4(rectValue.x, rectValue.y, rectValue.width, rectValue.height))) { } @@ -326,12 +585,14 @@ Property::Value::Value(const AngleAxis& 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) -: mImpl(new Impl(stringValue)) +Property::Value::Value(std::string stringValue) +: mImpl(new Impl(std::move(stringValue))) { } @@ -348,22 +609,12 @@ Property::Value::Value(const char* stringValue) } } -Property::Value::Value(Property::Array& arrayValue) -: mImpl(new Impl(arrayValue)) -{ -} - -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) +Property::Value::Value(Property::Map mapValue) : mImpl(new Impl(std::move(mapValue))) { } @@ -374,7 +625,7 @@ Property::Value::Value(const Extents& extentsValue) } Property::Value::Value(const std::initializer_list& values) -: mImpl(new Impl(values)) +: mImpl(new Impl(Property::Map(values))) { } @@ -415,7 +666,7 @@ Property::Value::Value(Type type) } case Property::RECTANGLE: { - mImpl = new Impl(Rect(0, 0, 0, 0)); + mImpl = new Impl(Rect()); break; } case Property::ROTATION: @@ -468,7 +719,7 @@ Property::Value::Value(const Property::Value& value) operator=(value); } -Property::Value::Value(Property::Value&& value) +Property::Value::Value(Property::Value&& value) noexcept : mImpl(value.mImpl) { value.mImpl = nullptr; @@ -481,181 +732,26 @@ Property::Value& Property::Value::operator=(const Property::Value& 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) { @@ -674,21 +770,24 @@ 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 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; } @@ -698,14 +797,19 @@ bool Property::Value::Get(float& floatValue) const bool converted = false; if(mImpl) { - if(mImpl->type == FLOAT) + if(mImpl->GetType() == FLOAT) { - floatValue = mImpl->floatValue; + floatValue = mImpl->GetFloat(); converted = true; } - else if(IsIntegerType(mImpl->type)) + else if(mImpl->GetType() == BOOLEAN) { - floatValue = static_cast(mImpl->integerValue); + floatValue = static_cast(mImpl->GetBool()); + converted = true; + } + else if(mImpl->GetType() == INTEGER) + { + floatValue = static_cast(mImpl->GetInt()); converted = true; } } @@ -717,14 +821,19 @@ bool Property::Value::Get(int32_t& integerValue) const bool converted = false; if(mImpl) { - if(IsIntegerType(mImpl->type)) + if(mImpl->GetType() == INTEGER) + { + integerValue = mImpl->GetInt(); + converted = true; + } + else if(mImpl->GetType() == BOOLEAN) { - integerValue = mImpl->integerValue; + integerValue = mImpl->GetBool(); converted = true; } - else if(mImpl->type == FLOAT) + else if(mImpl->GetType() == FLOAT) { - integerValue = static_cast(mImpl->floatValue); + integerValue = static_cast(mImpl->GetFloat()); converted = true; } } @@ -736,10 +845,19 @@ bool Property::Value::Get(Vector2& vectorValue) const bool converted = false; 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 + vectorValue = mImpl->GetVector3(); converted = true; } } @@ -751,15 +869,19 @@ bool Property::Value::Get(Vector3& vectorValue) const bool converted = false; if(mImpl) { - // type cannot change in mImpl so vector is allocated - if(mImpl->type == VECTOR3 || mImpl->type == VECTOR4) + if(mImpl->GetType() == VECTOR4) + { + vectorValue = mImpl->GetVector4(); + converted = true; + } + else if(mImpl->GetType() == VECTOR2) { - vectorValue = *(mImpl->vector3Value); // if Vector4 only x,y,z are assigned + vectorValue = mImpl->GetVector2(); converted = true; } - else if(mImpl->type == VECTOR2) + else if(mImpl->GetType() == VECTOR3) { - vectorValue = *(mImpl->vector2Value); + vectorValue = mImpl->GetVector3(); converted = true; } } @@ -771,19 +893,19 @@ bool Property::Value::Get(Vector4& vectorValue) const bool converted = false; if(mImpl) { - if(mImpl->type == VECTOR4) // type cannot change in mImpl so vector is allocated + if(mImpl->GetType() == VECTOR4) { - vectorValue = *(mImpl->vector4Value); + vectorValue = mImpl->GetVector4(); converted = true; } - else if(mImpl->type == VECTOR2) + else if(mImpl->GetType() == VECTOR2) { - vectorValue = *(mImpl->vector2Value); + vectorValue = mImpl->GetVector2(); converted = true; } - else if(mImpl->type == VECTOR3) + else if(mImpl->GetType() == VECTOR3) { - vectorValue = *(mImpl->vector3Value); + vectorValue = mImpl->GetVector3(); converted = true; } } @@ -793,9 +915,9 @@ bool Property::Value::Get(Vector4& vectorValue) 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); + matrixValue = mImpl->GetMatrix3(); converted = true; } return converted; @@ -804,9 +926,9 @@ bool Property::Value::Get(Matrix3& 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); + matrixValue = mImpl->GetMatrix(); converted = true; } return converted; @@ -815,9 +937,9 @@ bool Property::Value::Get(Matrix& matrixValue) 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; @@ -826,9 +948,9 @@ bool Property::Value::Get(Rect& rectValue) 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); + angleAxisValue = mImpl->GetAngleAxis(); converted = true; } return converted; @@ -837,9 +959,10 @@ bool Property::Value::Get(AngleAxis& angleAxisValue) 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); + auto& obj = mImpl->GetAngleAxis(); + quaternionValue = Quaternion(obj.angle, obj.axis); converted = true; } return converted; @@ -848,9 +971,9 @@ bool Property::Value::Get(Quaternion& quaternionValue) 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; @@ -859,9 +982,9 @@ bool Property::Value::Get(std::string& stringValue) 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); + arrayValue = mImpl->GetArray(); converted = true; } return converted; @@ -870,50 +993,69 @@ bool Property::Value::Get(Property::Array& arrayValue) 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; } +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->type == EXTENTS) + if(mImpl->GetType() == EXTENTS) { - extentsValue = *(mImpl->extentsValue); + extentsValue = mImpl->GetExtents(); converted = true; } - else if(mImpl->type == VECTOR4) + else if(mImpl->GetType() == VECTOR4) { - extentsValue.start = static_cast(mImpl->vector4Value->x); - extentsValue.end = static_cast(mImpl->vector4Value->y); - extentsValue.top = static_cast(mImpl->vector4Value->z); - extentsValue.bottom = static_cast(mImpl->vector4Value->w); + 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; } } @@ -924,78 +1066,78 @@ std::ostream& operator<<(std::ostream& stream, const Property::Value& value) { 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; + 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: diff --git a/dali/public-api/object/property-value.h b/dali/public-api/object/property-value.h index d04c9e9..d9e6f7d 100644 --- a/dali/public-api/object/property-value.h +++ b/dali/public-api/object/property-value.h @@ -163,7 +163,7 @@ public: * @SINCE_1_0.0 * @param[in] stringValue A string */ - Value(const std::string& stringValue); + Value(std::string stringValue); /** * @brief Creates a string property value. @@ -176,34 +176,18 @@ public: /** * @brief Creates an array property value. * - * @SINCE_1_0.0 - * @param[in] arrayValue An array - */ - Value(Property::Array& arrayValue); - - /** - * @brief Creates an array property value. - * - * @SINCE_1_4.16 - * @param[in] arrayValue An r-value array + * @SINCE_1_9.30 + * @param[in] arrayValue A property array */ - Value(Property::Array&& arrayValue); + Value(Property::Array arrayValue); /** * @brief Creates a map property value. * - * @SINCE_1_0.0 - * @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 + * @SINCE_1_9.30 + * @param[in] mapValue A property map */ - Value(Property::Map&& mapValue); + Value(Property::Map mapValue); /** * @brief Create a map property value from an initializer_list. @@ -256,7 +240,7 @@ public: * @SINCE_1_4.16 * @param[in] value The property value to move from */ - Value(Value&& value); + Value(Value&& value) noexcept; /** * @brief Assigns a property value. @@ -274,7 +258,7 @@ public: * @param[in] value The property value to move from * @return a reference to this */ - Value& operator=(Value&& value); + Value& operator=(Value&& value) noexcept; /** * @brief Non-virtual destructor. @@ -486,20 +470,36 @@ public: bool Get(Property::Map& mapValue) const; /** - * @brief Retrieves the Array API of the Property::Value without copying the contents of the map. + * @brief Retrieves the Array API of the Property::Value without copying the contents of the array. * - * @SINCE_1_0.0 + * @SINCE_1_9.32 * @return The Array API of the Property::Value or NULL if not a Property::Array */ - Property::Array* GetArray() const; + const Property::Array* GetArray() const; + + /** + * @brief Retrieves the Array API of the Property::Value without copying the contents of the array. + * + * @SINCE_1_9.32 + * @return The Array API of the Property::Value or NULL if not a Property::Array + */ + Property::Array* GetArray(); /** * @brief Retrieves the Map API of the Property::Value without copying the contents of the map. * - * @SINCE_1_0.0 + * @SINCE_1_9.32 + * @return The Map API of the Property::Value or NULL if not a Property::Map + */ + const Property::Map* GetMap() const; + + /** + * @brief Retrieves the Map API of the Property::Value without copying the contents of the map. + * + * @SINCE_1_9.32 * @return The Map API of the Property::Value or NULL if not a Property::Map */ - Property::Map* GetMap() const; + Property::Map* GetMap(); /** * @brief Retrieves an extents. diff --git a/packaging/dali.spec b/packaging/dali.spec index a3f82bc..25b5042 100644 --- a/packaging/dali.spec +++ b/packaging/dali.spec @@ -1,6 +1,6 @@ Name: dali2 Summary: DALi 3D Engine -Version: 1.9.31 +Version: 1.9.32 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT