--- /dev/null
+///
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <tet_api.h>
+
+#include <dali/public-api/dali-core.h>
+
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+static void Startup();
+static void Cleanup();
+
+extern "C" {
+ void (*tet_startup)() = Startup;
+ void (*tet_cleanup)() = Cleanup;
+}
+
+enum {
+ POSITIVE_TC_IDX = 0x01,
+ NEGATIVE_TC_IDX,
+};
+
+#define MAX_NUMBER_OF_TESTS 10000
+extern "C" {
+ struct tet_testlist tet_testlist[MAX_NUMBER_OF_TESTS];
+}
+
+TEST_FUNCTION( UtcDaliAnyConstructors, POSITIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliAnyAssignmentOperators, POSITIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliAnyNegativeAssignmentOperators, NEGATIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliAnyGetType, POSITIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliAnyGet, POSITIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliAnyNegativeGet, NEGATIVE_TC_IDX );
+
+// Called only once before first test is run.
+static void Startup()
+{
+}
+
+// Called only once after last test is run
+static void Cleanup()
+{
+}
+
+static void UtcDaliAnyConstructors()
+{
+ TestApplication application;
+
+ tet_infoline("Test Any constructors.");
+
+ // Test default constructor.
+ Any value;
+
+ DALI_TEST_CHECK( typeid( void ) == value.GetType() );
+
+ // Test constructor Any( const Type& )
+ Any value1 = 4u;
+
+ // Test constructor Any( const Any& )
+ Any value2 = value1;
+
+ // Test constructor Any( const Any& ) with a non initialized Any
+ Any value3 = value;
+
+ DALI_TEST_CHECK( typeid( unsigned int ) == value1.GetType() );
+ DALI_TEST_CHECK( typeid( unsigned int ) == value2.GetType() );
+ DALI_TEST_CHECK( typeid( void ) == value3.GetType() );
+
+ unsigned int uiValue1 = 0u;
+ unsigned int uiValue2 = 0u;
+ value1.Get( uiValue1 );
+ value2.Get( uiValue2 );
+
+ DALI_TEST_EQUALS( uiValue1, uiValue2, TEST_LOCATION );
+}
+
+static void UtcDaliAnyAssignmentOperators()
+{
+ TestApplication application;
+
+ tet_infoline("Test assignment operators.");
+
+ float fValue = 0.f;
+
+ Any value1;
+
+ value1 = 4.f; // Test operator=( const Type& ) when current object is not initialized.
+
+ value1.Get( fValue );
+
+ DALI_TEST_EQUALS( fValue, 4.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+ Any value2 = 0.f;
+
+ value2 = 9.f; // Test operator=( const Type& ).
+
+ value2.Get( fValue );
+
+ DALI_TEST_EQUALS( fValue, 9.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+ Any value3 = 5.f;
+
+ value1 = value3; // Test operator=( const Any& ).
+
+ value1.Get( fValue );
+
+ DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+ Any value4;
+
+ value4 = value3; // Test operator=( const Any& ) when current object is not initialized.
+
+ value4.Get( fValue );
+
+ DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+ // Test assign a value to value3 doesn't modify value1.
+ value3 = 3.f;
+
+ value1.Get( fValue );
+
+ DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+ value3.Get( fValue );
+
+ DALI_TEST_EQUALS( fValue, 3.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+ // Test the branch when copying the same object.
+ Any value5 = 3.f;
+ Any& value6( value5 );
+
+ value6 = value5;
+
+ value6.Get( fValue );
+ DALI_TEST_EQUALS( fValue, 3.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+}
+
+static void UtcDaliAnyNegativeAssignmentOperators()
+{
+ TestApplication application;
+
+ tet_infoline("Test assignment operators.");
+
+ Any value1 = 4.f;
+ Any value2 = 5u;
+
+ bool assert = false;
+
+ try
+ {
+ value1 = value2; // Test operator=( const Any& );
+ }
+ catch( Dali::DaliException& e )
+ {
+ tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
+ assert = true;
+ }
+
+ if( assert )
+ {
+ tet_result( TET_PASS );
+ }
+ else
+ {
+ tet_result( TET_FAIL );
+ }
+}
+
+static void UtcDaliAnyGetType()
+{
+ TestApplication application;
+
+ tet_infoline("Test GetType().");
+
+ Any value;
+
+ DALI_TEST_CHECK( typeid( void ) == value.GetType() );
+
+ value = 5.f;
+
+ DALI_TEST_CHECK( typeid( float ) == value.GetType() );
+}
+
+static void UtcDaliAnyGet()
+{
+ TestApplication application;
+
+ tet_infoline("Test Get().");
+
+ Any value1( 5.f );
+
+ float fValue = value1.Get<float>();
+
+ DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+ fValue = 0.f;
+ value1.Get( fValue );
+ DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+}
+
+static void UtcDaliAnyNegativeGet()
+{
+ TestApplication application;
+ tet_infoline("Test Get().");
+
+ Any value1;
+ Any value2( 5.f );
+
+ bool assert1 = false;
+ bool assert2 = false;
+
+ unsigned int uiValue = 0u;
+
+ try
+ {
+ uiValue = value1.Get< unsigned int >();
+ }
+
+ catch( Dali::DaliException& e )
+ {
+ tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
+ assert1 = true;
+ }
+
+ try
+ {
+ uiValue = value2.Get< unsigned int >();
+ }
+
+ catch( Dali::DaliException& e )
+ {
+ tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
+ assert2 = true;
+ }
+
+ if( assert1 && assert2 )
+ {
+ tet_result( TET_PASS );
+ }
+ else
+ {
+ tet_result( TET_FAIL );
+ }
+ uiValue++; // supresss warning from unused variable
+}
+
--- /dev/null
+#ifndef __DALI_ANY_TYPE_H__
+#define __DALI_ANY_TYPE_H__
+
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @addtogroup CAPI_DALI_OBJECT_MODULE
+ * @{
+ */
+
+// EXTERNAL INCLUDES
+#include <typeinfo> // operator typeid
+
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+/**
+ * Stores a value of any type.
+ *
+ * @note Assignments of values with different types are now allowed to replicate Any behaviour
+ *
+ * Examples of use:
+ * \code{.cpp}
+ * Any uintVariable = 5u;
+ * Any floatVariable( 4.5f );
+ * Any strVariable( std::string( "Hello world" ) );
+ * uintVariable = 1u;
+ * unsigned int variable = AnyCast< unsigned int >( uintVariable );
+ * if ( typeid( int ) == uintVariable.GetType() )
+ * \endcode
+ */
+class Any
+{
+public:
+ /**
+ * Default constructor.
+ */
+ Any();
+
+ /**
+ * Destructor. Free resources.
+ */
+ ~Any();
+
+/**
+ * @brief Pass Assert message
+ *
+ * @param assertMessage Assert message to report
+ */
+ static void AssertAlways( const char* assertMessage );
+
+ /**
+ * @brief Constructs a Any type with the given value.
+ *
+ * @param[in] value The given value.
+ */
+ template<typename Type>
+ Any( const Type& value )
+ : mContainer( new AnyContainerImpl<Type>( value ) )
+ {
+ }
+
+ /**
+ * Copy Constructor.
+ * @param [in] any Any to be copied.
+ */
+ Any( const Any& any )
+ {
+ // If container isn't empty then copy the container?
+ if ( NULL != any.mContainer )
+ {
+ mContainer = any.mContainer->mCloneFunc( *any.mContainer );
+ }
+ else
+ {
+ // Otherwise mark new container as empty
+ mContainer = NULL;
+ }
+ }
+
+ /**
+ * @brief Assigns a given value to the Any type.
+ *
+ * @note If the types are different, then the current container will be re-created.
+ *
+ * @param[in] value The given value.
+ */
+ template<typename Type>
+ Any& operator=( const Type& value )
+ {
+
+ // If the container is empty then assign the new value
+ if ( NULL == mContainer )
+ {
+ mContainer = new AnyContainerImpl< Type >( value );
+ }
+ else
+ {
+ // Check to see if this type is compatible with current container?
+ if ( mContainer->GetType() == typeid( Type ) )
+ {
+ // Same type so just set the new value
+ static_cast< AnyContainerImpl< Type >* >( mContainer )->SetValue( value );
+ }
+ else
+ {
+ // Incompatible types, so delete old container and assign a new one with this type and value
+ mContainer->mDeleteFunc( mContainer );
+ mContainer = new AnyContainerImpl< Type >( value );
+ }
+ }
+ return *this;
+ }
+
+ /**
+ * @brief Assignment operator.
+ *
+ * @note Asserts if values of different types are assigned.
+ *
+ * @param [in] any Any to be assigned.
+ */
+ Any& operator=( const Any& any );
+
+ /**
+ * @brief Get a value of type Type from container
+ *
+ * @param type destination of type Type to write to
+ */
+ template<typename Type>
+ void Get( Type& type )
+ {
+ type = Get<Type>();
+ }
+
+ /**
+ * @brief Returns the type info of the stored value.
+ *
+ * @note Returns the info of the void type if there is no value stored.
+ */
+ const std::type_info& GetType() const;
+
+ /**
+ * @brief Retrieves the stored value in the Any type.
+ *
+ * @return The stored value.
+ */
+ template<typename Type>
+ const Type& Get() const
+ {
+
+ if ( NULL == mContainer )
+ {
+ AssertAlways( "Any::Get(). mContainer is NULL" );
+ }
+
+ // Check if the value has the same value than the Any type.
+ if( mContainer->GetType() != typeid( Type ) )
+ {
+ AssertAlways( "Any::Get(). Trying to retrieve a value of a different type than the template one." );
+ }
+ return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetValue();
+ }
+
+ /**
+ * @brief Return pointer of Type to the value stored
+ *
+ * @return pointer to the value or NULL if no value is contained
+ */
+ template<typename Type>
+ Type* GetPointer()
+ {
+ if( NULL == mContainer )
+ {
+ return NULL;
+ }
+ // Check if the value has the same value than the Any type.
+ if( mContainer->GetType() != typeid( Type ) )
+ {
+ AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
+ }
+ return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
+ }
+
+ /**
+ * @brief Returns whether container holds a value
+ *
+ * @return true or false
+ */
+ bool Empty()
+ {
+ return ( NULL == mContainer ) ? true : false;
+ }
+
+ struct AnyContainerBase; // Forward declaration for typedef
+ typedef AnyContainerBase* (*CloneFunc)( const AnyContainerBase& base );
+ typedef void (*DeleteFunc)( const AnyContainerBase* base );
+
+ /**
+ * Base container to hold type for match verification and instance cloning function
+ *
+ */
+ struct AnyContainerBase
+ {
+ /**
+ * @brief Constructor of base container
+ *
+ * @param type typeid of container
+ * @param cloneFunc Cloning function to replicate this container type
+ * @param deleteFunc Deleting function to destroy this container type
+ */
+ AnyContainerBase( const std::type_info& type, CloneFunc cloneFunc, DeleteFunc deleteFunc )
+ : mType( type ),
+ mCloneFunc( cloneFunc ),
+ mDeleteFunc( deleteFunc )
+ {}
+
+ /**
+ * @brief Get the typeid of this container
+ *
+ * @return type
+ */
+ const std::type_info& GetType() const
+ {
+ return mType;
+ }
+
+ const::std::type_info& mType; // typeID
+ CloneFunc mCloneFunc; // cloning function for this container
+ DeleteFunc mDeleteFunc; // deleting function for this container
+ };
+
+
+ /**
+ * @brief Templated Clone function from container base
+ *
+ * @param base reference to container
+ */
+ template<typename Type>
+ struct AnyContainerImplCloner
+ {
+ static AnyContainerBase* Clone( const AnyContainerBase& base )
+ {
+ return new AnyContainerImpl< Type >( static_cast< AnyContainerImpl< Type > >( base ) );
+ }
+ };
+
+ /**
+ * @brief Templated Delete function from container base
+ *
+ * @param base pointer to container
+ */
+ template<typename Type>
+ struct AnyContainerImplDelete
+ {
+ static void Delete( const AnyContainerBase* base )
+ {
+ delete ( static_cast< const AnyContainerImpl< Type >* > ( base ) );
+ }
+ };
+
+ /**
+ * @brief Templated class to hold value for type
+ *
+ */
+ template<typename Type>
+ class AnyContainerImpl : public AnyContainerBase
+ {
+ public:
+
+ /**
+ * @brief Constructor to create container holding value of type Type
+ *
+ * @param value Value of Type
+ */
+ AnyContainerImpl( const Type& value )
+ : AnyContainerBase( typeid( Type ),
+ static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
+ static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) ),
+ mValue( value )
+ {}
+
+ /**
+ * @brief Constructor to create new container of type from and existing container (cloning)
+ *
+ * @param base reference to base container to copy from
+ */
+ AnyContainerImpl( const AnyContainerBase& base )
+ : AnyContainerBase( typeid( Type ),
+ static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
+ static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) )
+ {
+ mValue = static_cast< const AnyContainerImpl& >( base ).GetValue();
+ }
+
+ /**
+ * @brief Get the container's stored value
+ *
+ * @return value of Type
+ */
+ const Type& GetValue() const
+ {
+ return mValue;
+ }
+
+ void SetValue( const Type& value )
+ {
+ mValue = value;
+ }
+
+ /**
+ * @brief Get a pointer to the value held
+ *
+ * @return pointer to the value of type Type
+ */
+ Type* GetPointerToValue()
+ {
+ return static_cast< Type* >( &mValue );
+ }
+
+ private:
+ Type mValue;
+ };
+
+ AnyContainerBase* mContainer;
+
+};
+
+/**
+ * AnyCast helper functions ( replicates boost functionality, but without exception generation )
+ */
+
+/**
+ * @brief Extract a pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
+ *
+ * @param any Pointer to an Any object
+ *
+ * @return Pointer to the Type held
+ */
+template<typename Type>inline Type* AnyCast( Any* any )
+{
+ return any->GetPointer<Type>();
+}
+
+/**
+ * @brief Extract a const pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
+ *
+ * @param any const Pointer to an Any object
+ *
+ * @return const Pointer to the Type held
+ */
+template<typename Type>inline const Type* AnyCast( const Any* any )
+{
+ return any->GetPointer<Type>();
+}
+
+/**
+ * @brief Extract a held value of type Type from an Any object from a reference to that Any object
+ *
+ * @param any reference to an Any object
+ *
+ * @return Type value of type Type
+ */
+template<typename Type>inline Type AnyCast( Any& any )
+{
+ return any.Get<Type>();
+}
+
+/**
+ * @brief Extract a held value of type Type from an Any object from a const reference to that Any object
+ *
+ * @param any reference to an Any object
+ *
+ * @return Type value of type Type
+ */
+template<typename Type>inline Type AnyCast( const Any& any )
+{
+ return any.Get<Type>();
+}
+
+} // namespace Dali
+
+/**
+ * @}
+ */
+#endif // __DALI_ANY_TYPE_H__
--- /dev/null
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// CLASS HEADER
+#include <dali/public-api/object/any.h>
+
+// EXTERNAL HEADERS
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+Any::Any()
+: mContainer( NULL )
+{
+}
+
+Any::~Any()
+{
+ // Call the implementation deletion function, which will invalidate mContainer
+
+ if ( NULL != mContainer )
+ {
+ mContainer->mDeleteFunc( mContainer );
+ mContainer = NULL;
+ }
+}
+
+Any& Any::operator=( const Any& any )
+{
+ if( &any != this )
+ {
+ if( NULL == any.mContainer )
+ {
+ delete mContainer;
+ mContainer = NULL;
+ }
+ else
+ {
+ AnyContainerBase* tmp = mContainer;
+
+ if( NULL != mContainer )
+ {
+ // Check if two Any types have the same type. Avoids assignments of values with different types.
+ if( mContainer->GetType() != any.GetType() )
+ {
+ AssertAlways( "Any::operator=( const Any& Any ). Trying to assign two values with different types." );
+ }
+ }
+
+ // Clone the correct templated object
+ mContainer = any.mContainer->mCloneFunc( *any.mContainer );
+
+ // Deletes previous container.
+ delete tmp;
+ }
+ }
+
+ return *this;
+}
+
+const std::type_info& Any::GetType() const
+{
+ return mContainer ? mContainer->GetType() : typeid( void );
+}
+
+void Any::AssertAlways( const char* assertMessage )
+{
+ DALI_LOG_ERROR_NOFN( assertMessage );
+ throw Dali::DaliException( assertMessage, "" );
+}
+
+
+} //namespace Dali