1 #ifndef __DALI_ANY_TYPE_H__
2 #define __DALI_ANY_TYPE_H__
5 * Copyright (c) 2014 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
26 #include <dali/public-api/common/dali-common.h>
32 * @brief Stores a value of any type.
36 * Any uintVariable = 5u;
37 * Any floatVariable( 4.5f );
38 * Any strVariable( std::string( "Hello world" ) );
40 * unsigned int variable = AnyCast< unsigned int >( uintVariable );
41 * if ( typeid( int ) == uintVariable.GetType() )
48 * Default constructor.
50 DALI_IMPORT_API Any();
53 * Destructor. Free resources.
55 DALI_IMPORT_API ~Any();
58 * @brief Pass Assert message
60 * @param assertMessage Assert message to report
62 DALI_IMPORT_API static void AssertAlways( const char* assertMessage );
65 * @brief Constructs a Any type with the given value.
67 * @param[in] value The given value.
69 template<typename Type>
70 Any( const Type& value )
71 : mContainer( new AnyContainerImpl<Type>( value ) )
77 * @param [in] any Any to be copied.
81 // If container isn't empty then copy the container?
82 if ( NULL != any.mContainer )
84 mContainer = any.mContainer->mCloneFunc( *any.mContainer );
88 // Otherwise mark new container as empty
94 * @brief Assigns a given value to the Any type.
96 * @note If the types are different, then the current container will be re-created.
98 * @param[in] value The given value.
100 template<typename Type>
101 Any& operator=( const Type& value )
103 // If the container is empty then assign the new value
104 if ( NULL == mContainer )
106 mContainer = new AnyContainerImpl< Type >( value );
110 // Check to see if this type is compatible with current container?
111 if ( mContainer->GetType() == typeid( Type ) )
113 // Same type so just set the new value
114 static_cast< AnyContainerImpl< Type >* >( mContainer )->SetValue( value );
118 // Incompatible types, so delete old container and assign a new one with this type and value
119 mContainer->mDeleteFunc( mContainer );
120 mContainer = new AnyContainerImpl< Type >( value );
127 * @brief Assignment operator.
129 * @exception DaliException If parameter any is of a different type.
131 * @param [in] any Any to be assigned which contains a value of identical type to current contents.
133 DALI_IMPORT_API Any& operator=( const Any& any );
136 * @brief Get a value of type Type from container
138 * @param type destination of type Type to write to
140 template<typename Type>
141 void Get( Type& type ) const
147 * @brief Returns the type info of the stored value.
149 * @return The std::type_info of the stored value or the type info of the void
150 * type if there is no value stored.
152 DALI_IMPORT_API const std::type_info& GetType() const;
155 * @brief Retrieves the stored value in the Any type.
157 * @return The stored value.
159 template<typename Type>
160 const Type& Get() const
163 if ( NULL == mContainer )
165 AssertAlways( "Any::Get(). mContainer is NULL" );
168 // Check if the value has the same value than the Any type.
169 if( mContainer->GetType() != typeid( Type ) )
171 AssertAlways( "Any::Get(). Trying to retrieve a value of a different type than the template one." );
173 return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetValue();
177 * @brief Return pointer of Type to the value stored
179 * @return pointer to the value or NULL if no value is contained
181 template<typename Type>
184 if( NULL == mContainer )
188 // Check if the value has the same value than the Any type.
189 if( mContainer->GetType() != typeid( Type ) )
191 AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
193 return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
197 * @brief Return pointer of Type to the value stored
199 * @return pointer to the value or NULL if no value is contained
201 template<typename Type>
202 const Type* GetPointer() const
204 if( NULL == mContainer )
208 // Check if the value has the same value than the Any type.
209 if( mContainer->GetType() != typeid( Type ) )
211 AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
213 return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
217 * @brief Returns whether container holds a value
219 * @return true if the container is empty, else false.
223 return ( NULL == mContainer ) ? true : false;
226 struct AnyContainerBase; // Forward declaration for typedef
227 typedef AnyContainerBase* (*CloneFunc)( const AnyContainerBase& base );
228 typedef void (*DeleteFunc)( const AnyContainerBase* base );
231 * Base container to hold type for match verification and instance cloning function
234 struct AnyContainerBase
237 * @brief Constructor of base container
239 * @param type typeid of container
240 * @param cloneFunc Cloning function to replicate this container type
241 * @param deleteFunc Deleting function to destroy this container type
243 AnyContainerBase( const std::type_info& type, CloneFunc cloneFunc, DeleteFunc deleteFunc )
245 mCloneFunc( cloneFunc ),
246 mDeleteFunc( deleteFunc )
250 * @brief Get the typeid of this container
254 const std::type_info& GetType() const
259 const::std::type_info& mType; // typeID
260 CloneFunc mCloneFunc; // cloning function for this container
261 DeleteFunc mDeleteFunc; // deleting function for this container
266 * @brief Templated Clone function from container base
268 * @param base reference to container
270 template<typename Type>
271 struct AnyContainerImplCloner
273 static AnyContainerBase* Clone( const AnyContainerBase& base )
275 return new AnyContainerImpl< Type >( static_cast< AnyContainerImpl< Type > >( base ) );
280 * @brief Templated Delete function from container base
282 * @param base pointer to container
284 template<typename Type>
285 struct AnyContainerImplDelete
287 static void Delete( const AnyContainerBase* base )
289 delete ( static_cast< const AnyContainerImpl< Type >* > ( base ) );
294 * @brief Templated class to hold value for type
297 template<typename Type>
298 class AnyContainerImpl : public AnyContainerBase
303 * @brief Constructor to create container holding value of type Type
305 * @param value Value of Type
307 AnyContainerImpl( const Type& value )
308 : AnyContainerBase( typeid( Type ),
309 static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
310 static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) ),
315 * @brief Constructor to create new container of type from and existing container (cloning)
317 * @param base reference to base container to copy from
319 AnyContainerImpl( const AnyContainerBase& base )
320 : AnyContainerBase( typeid( Type ),
321 static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
322 static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) )
324 mValue = static_cast< const AnyContainerImpl& >( base ).GetValue();
328 * @brief Get the container's stored value
330 * @return value of type Type
332 const Type& GetValue() const
338 * @brief Set the container's stored value
340 * @param value of type Type
342 void SetValue( const Type& value )
348 * @brief Get a pointer to the value held
350 * @return pointer to the value of type Type
352 Type* GetPointerToValue()
354 return static_cast< Type* >( &mValue );
358 * @brief Get a pointer to the value held
360 * @return pointer to the value of type Type
362 const Type* GetPointerToValue() const
364 return static_cast< const Type* >( &mValue );
371 AnyContainerBase* mContainer;
376 * AnyCast helper functions
380 * @brief Extract a pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
382 * @param any Pointer to an Any object
384 * @return Pointer to the Type held
386 template<typename Type>
387 inline Type* AnyCast( Any* any )
389 return any->GetPointer<Type>();
393 * @brief Extract a const pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
395 * @param any const Pointer to an Any object
397 * @return const Pointer to the Type held
399 template<typename Type>
400 inline const Type* AnyCast( const Any* any )
402 return any->GetPointer<Type>();
406 * @brief Extract a held value of type Type from an Any object from a reference to that Any object
408 * @param any reference to an Any object
410 * @return Type value of type Type
412 template<typename Type>
413 inline Type AnyCast( Any& any )
415 return any.Get<Type>();
419 * @brief Extract a held value of type Type from an Any object from a const reference to that Any object
421 * @param any reference to an Any object
423 * @return Type value of type Type
425 template<typename Type>
426 inline Type AnyCast( const Any& any )
428 return any.Get<Type>();
432 * @brief Extract a reference to the held value of type Type from an Any object from a reference to that Any object
434 * @param any reference to an Any object
436 * @return A reference to the Type value of type Type
438 template<typename Type>
439 inline Type& AnyCastReference( Any& any )
441 return any.Get<Type>();
445 * @brief Extract a const reference to the held value of type Type from an Any object from a const reference to that Any object
447 * @param any reference to an Any object
449 * @return A const reference to the Type value of type Type
451 template<typename Type>
452 inline const Type& AnyCastReference( const Any& any )
454 return any.Get<Type>();
459 #endif // __DALI_ANY_TYPE_H__