1 #ifndef __DALI_ANY_TYPE_H__
2 #define __DALI_ANY_TYPE_H__
5 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 #include <typeinfo> // operator typeid
23 #include <cstddef> // NULL
26 #include <dali/public-api/common/dali-common.h>
31 * @addtogroup dali_core_object
36 * @brief Stores a value of any type.
40 * Any uintVariable = 5u;
41 * Any floatVariable( 4.5f );
42 * Any strVariable( std::string( "Hello world" ) );
44 * uint32_t variable = AnyCast< uint32_t >( uintVariable );
45 * if ( typeid( int ) == uintVariable.GetType() )
53 * @brief Default constructor.
59 * @brief Destructor. Free resources.
65 * @brief Passes Assert message.
68 * @param[in] assertMessage Assert message to report
70 DALI_CORE_API static void AssertAlways( const char* assertMessage );
73 * @brief Constructs a Any type with the given value.
76 * @param[in] value The given value
78 template<typename Type>
79 Any( const Type& value )
80 : mContainer( new AnyContainerImpl<Type>( value ) )
85 * @brief Copy Constructor.
87 * @param[in] any Any to be copied
91 // If container isn't empty then copy the container?
92 if ( NULL != any.mContainer )
94 mContainer = any.mContainer->mCloneFunc( *any.mContainer );
98 // Otherwise mark new container as empty
104 * @brief Assigns a given value to the Any type.
107 * @param[in] value The given value
108 * @return A reference to this
109 * @note If the types are different, then the current container will be re-created.
112 template<typename Type>
113 Any& operator=( const Type& value )
115 // If the container is empty then assign the new value
116 if ( NULL == mContainer )
118 mContainer = new AnyContainerImpl< Type >( value );
122 // Check to see if this type is compatible with current container?
123 if ( mContainer->GetType() == typeid( Type ) )
125 // Same type so just set the new value
126 static_cast< AnyContainerImpl< Type >* >( mContainer )->SetValue( value );
130 // Incompatible types, so delete old container and assign a new one with this type and value
131 mContainer->mDeleteFunc( mContainer );
132 mContainer = new AnyContainerImpl< Type >( value );
139 * @brief Assignment operator.
142 * @param[in] any Any to be assigned which contains a value of identical type to current contents.
143 * @return A reference to this
144 * @exception DaliException If parameter any is of a different type.
147 DALI_CORE_API Any& operator=( const Any& any );
150 * @brief Gets a value of type Type from container.
153 * @param[in] type destination of type Type to write to
155 template<typename Type>
156 void Get( Type& type ) const
162 * @brief Returns the type info of the stored value.
165 * @return The std::type_info of the stored value or the type info of the void
166 * type if there is no value stored
168 DALI_CORE_API const std::type_info& GetType() const;
171 * @brief Retrieves the stored value in the Any type.
174 * @return The stored value
176 template<typename Type>
177 const Type& Get() const
179 if ( NULL == mContainer )
181 AssertAlways( "Any::Get(). mContainer is NULL" );
183 else if( mContainer->GetType() != typeid( Type ) ) // Check if the value has the same value than the Any type.
185 AssertAlways( "Any::Get(). Trying to retrieve a value of a different type than the template one." );
187 return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetValue();
191 * @brief Returns pointer of Type to the value stored.
194 * @return pointer to the value, or NULL if no value is contained
196 template<typename Type>
199 if( NULL == mContainer )
203 // Check if the value has the same value than the Any type.
204 if( mContainer->GetType() != typeid( Type ) )
206 AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
208 return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
212 * @brief Returns pointer of Type to the value stored.
215 * @return pointer to the value, or NULL if no value is contained
217 template<typename Type>
218 const Type* GetPointer() const
220 if( NULL == mContainer )
224 // Check if the value has the same value than the Any type.
225 if( mContainer->GetType() != typeid( Type ) )
227 AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
229 return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
233 * @brief Returns whether container holds a value.
236 * @return @c true if the container is empty, else @c false
240 return ( NULL == mContainer ) ? true : false;
243 struct AnyContainerBase; // Forward declaration for typedef
244 typedef AnyContainerBase* (*CloneFunc)( const AnyContainerBase& base );
245 typedef void (*DeleteFunc)( const AnyContainerBase* base );
248 * @brief Base container to hold type for match verification and instance cloning function.
252 struct AnyContainerBase
255 * @brief Constructor of base container.
258 * @param[in] type typeid of container
259 * @param[in] cloneFunc Cloning function to replicate this container type
260 * @param[in] deleteFunc Deleting function to destroy this container type
262 AnyContainerBase( const std::type_info& type, CloneFunc cloneFunc, DeleteFunc deleteFunc )
264 mCloneFunc( cloneFunc ),
265 mDeleteFunc( deleteFunc )
269 * @brief Gets the typeid of this container.
274 const std::type_info& GetType() const
279 const::std::type_info& mType; // typeID
280 CloneFunc mCloneFunc; // cloning function for this container
281 DeleteFunc mDeleteFunc; // deleting function for this container
286 * @brief Templated Clone function from container base.
289 * @param[in] base The reference to container
291 template<typename Type>
292 struct AnyContainerImplCloner
294 static AnyContainerBase* Clone( const AnyContainerBase& base )
296 return new AnyContainerImpl< Type >( static_cast< AnyContainerImpl< Type > >( base ) );
301 * @brief Templated Delete function from container base.
304 * @param[in] base The pointer to container
306 template<typename Type>
307 struct AnyContainerImplDelete
309 static void Delete( const AnyContainerBase* base )
311 delete ( static_cast< const AnyContainerImpl< Type >* > ( base ) );
316 * @brief Templated class to hold value for type.
320 template<typename Type>
321 class AnyContainerImpl : public AnyContainerBase
326 * @brief Constructor to create container holding value of type Type.
329 * @param[in] value Value of Type
331 AnyContainerImpl( const Type& value )
332 : AnyContainerBase( typeid( Type ),
333 static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
334 static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) ),
339 * @brief Constructor to create new container of type from and existing container (cloning).
342 * @param[in] base The reference to base container to copy from
344 AnyContainerImpl( const AnyContainerBase& base )
345 : AnyContainerBase( typeid( Type ),
346 static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
347 static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) )
349 mValue = static_cast< const AnyContainerImpl& >( base ).GetValue();
353 * @brief Gets the container's stored value.
356 * @return Value of type Type
358 const Type& GetValue() const
364 * @brief Sets the container's stored value.
367 * @param[in] value Value of type Type
369 void SetValue( const Type& value )
375 * @brief Gets a pointer to the value held.
378 * @return Pointer to the value of type Type
380 Type* GetPointerToValue()
382 return static_cast< Type* >( &mValue );
386 * @brief Gets a pointer to the value held.
389 * @return Pointer to the value of type Type
391 const Type* GetPointerToValue() const
393 return static_cast< const Type* >( &mValue );
400 AnyContainerBase* mContainer;
405 * AnyCast helper functions
409 * @brief Extracts a pointer to the held type of an Any object from a pointer to that Any object (NULL if empty).
412 * @param[in] any Pointer to an Any object
414 * @return Pointer to the Type held
416 template<typename Type>
417 inline Type* AnyCast( Any* any )
419 return any->GetPointer<Type>();
423 * @brief Extracts a const pointer to the held type of an Any object from a pointer to that Any object (NULL if empty).
426 * @param[in] any const Pointer to an Any object
428 * @return const Pointer to the Type held
430 template<typename Type>
431 inline const Type* AnyCast( const Any* any )
433 return any->GetPointer<Type>();
437 * @brief Extracts a held value of type Type from an Any object from a reference to that Any object.
440 * @param[in] any The reference to an Any object
442 * @return Type value of type Type
444 template<typename Type>
445 inline Type AnyCast( Any& any )
447 return any.Get<Type>();
451 * @brief Extracts a held value of type Type from an Any object from a const reference to that Any object.
454 * @param[in] any The reference to an Any object
456 * @return Type value of type Type
458 template<typename Type>
459 inline Type AnyCast( const Any& any )
461 return any.Get<Type>();
465 * @brief Extracts a reference to the held value of type Type from an Any object from a reference to that Any object
468 * @param[in] any The reference to an Any object
470 * @return A reference to the Type value of type Type
472 template<typename Type>
473 inline Type& AnyCastReference( Any& any )
475 return any.Get<Type>();
479 * @brief Extracts a const reference to the held value of type Type from an Any object from a const reference to that Any object.
482 * @param[in] any The reference to an Any object
484 * @return A const reference to the Type value of type Type
486 template<typename Type>
487 inline const Type& AnyCastReference( const Any& any )
489 return any.Get<Type>();
497 #endif // __DALI_ANY_TYPE_H__