1 #ifndef __DALI_ANY_TYPE_H__
2 #define __DALI_ANY_TYPE_H__
5 * Copyright (c) 2015 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 * unsigned int variable = AnyCast< unsigned int >( uintVariable );
45 * if ( typeid( int ) == uintVariable.GetType() )
52 * Default constructor.
54 DALI_IMPORT_API Any();
57 * Destructor. Free resources.
59 DALI_IMPORT_API ~Any();
62 * @brief Pass Assert message
64 * @param assertMessage Assert message to report
66 DALI_IMPORT_API static void AssertAlways( const char* assertMessage );
69 * @brief Constructs a Any type with the given value.
71 * @param[in] value The given value.
73 template<typename Type>
74 Any( const Type& value )
75 : mContainer( new AnyContainerImpl<Type>( value ) )
81 * @param [in] any Any to be copied.
85 // If container isn't empty then copy the container?
86 if ( NULL != any.mContainer )
88 mContainer = any.mContainer->mCloneFunc( *any.mContainer );
92 // Otherwise mark new container as empty
98 * @brief Assigns a given value to the Any type.
100 * @note If the types are different, then the current container will be re-created.
102 * @param[in] value The given value.
104 template<typename Type>
105 Any& operator=( const Type& value )
107 // If the container is empty then assign the new value
108 if ( NULL == mContainer )
110 mContainer = new AnyContainerImpl< Type >( value );
114 // Check to see if this type is compatible with current container?
115 if ( mContainer->GetType() == typeid( Type ) )
117 // Same type so just set the new value
118 static_cast< AnyContainerImpl< Type >* >( mContainer )->SetValue( value );
122 // Incompatible types, so delete old container and assign a new one with this type and value
123 mContainer->mDeleteFunc( mContainer );
124 mContainer = new AnyContainerImpl< Type >( value );
131 * @brief Assignment operator.
133 * @exception DaliException If parameter any is of a different type.
135 * @param [in] any Any to be assigned which contains a value of identical type to current contents.
137 DALI_IMPORT_API Any& operator=( const Any& any );
140 * @brief Get a value of type Type from container
142 * @param type destination of type Type to write to
144 template<typename Type>
145 void Get( Type& type ) const
151 * @brief Returns the type info of the stored value.
153 * @return The std::type_info of the stored value or the type info of the void
154 * type if there is no value stored.
156 DALI_IMPORT_API const std::type_info& GetType() const;
159 * @brief Retrieves the stored value in the Any type.
161 * @return The stored value.
163 template<typename Type>
164 const Type& Get() const
167 if ( NULL == mContainer )
169 AssertAlways( "Any::Get(). mContainer is NULL" );
172 // Check if the value has the same value than the Any type.
173 if( mContainer->GetType() != typeid( Type ) )
175 AssertAlways( "Any::Get(). Trying to retrieve a value of a different type than the template one." );
177 return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetValue();
181 * @brief Return pointer of Type to the value stored
183 * @return pointer to the value or NULL if no value is contained
185 template<typename Type>
188 if( NULL == mContainer )
192 // Check if the value has the same value than the Any type.
193 if( mContainer->GetType() != typeid( Type ) )
195 AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
197 return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
201 * @brief Return pointer of Type to the value stored
203 * @return pointer to the value or NULL if no value is contained
205 template<typename Type>
206 const Type* GetPointer() const
208 if( NULL == mContainer )
212 // Check if the value has the same value than the Any type.
213 if( mContainer->GetType() != typeid( Type ) )
215 AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
217 return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
221 * @brief Returns whether container holds a value
223 * @return true if the container is empty, else false.
227 return ( NULL == mContainer ) ? true : false;
230 struct AnyContainerBase; // Forward declaration for typedef
231 typedef AnyContainerBase* (*CloneFunc)( const AnyContainerBase& base );
232 typedef void (*DeleteFunc)( const AnyContainerBase* base );
235 * Base container to hold type for match verification and instance cloning function
238 struct AnyContainerBase
241 * @brief Constructor of base container
243 * @param type typeid of container
244 * @param cloneFunc Cloning function to replicate this container type
245 * @param deleteFunc Deleting function to destroy this container type
247 AnyContainerBase( const std::type_info& type, CloneFunc cloneFunc, DeleteFunc deleteFunc )
249 mCloneFunc( cloneFunc ),
250 mDeleteFunc( deleteFunc )
254 * @brief Get the typeid of this container
258 const std::type_info& GetType() const
263 const::std::type_info& mType; // typeID
264 CloneFunc mCloneFunc; // cloning function for this container
265 DeleteFunc mDeleteFunc; // deleting function for this container
270 * @brief Templated Clone function from container base
272 * @param base reference to container
274 template<typename Type>
275 struct AnyContainerImplCloner
277 static AnyContainerBase* Clone( const AnyContainerBase& base )
279 return new AnyContainerImpl< Type >( static_cast< AnyContainerImpl< Type > >( base ) );
284 * @brief Templated Delete function from container base
286 * @param base pointer to container
288 template<typename Type>
289 struct AnyContainerImplDelete
291 static void Delete( const AnyContainerBase* base )
293 delete ( static_cast< const AnyContainerImpl< Type >* > ( base ) );
298 * @brief Templated class to hold value for type
301 template<typename Type>
302 class AnyContainerImpl : public AnyContainerBase
307 * @brief Constructor to create container holding value of type Type
309 * @param value Value of Type
311 AnyContainerImpl( const Type& value )
312 : AnyContainerBase( typeid( Type ),
313 static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
314 static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) ),
319 * @brief Constructor to create new container of type from and existing container (cloning)
321 * @param base reference to base container to copy from
323 AnyContainerImpl( const AnyContainerBase& base )
324 : AnyContainerBase( typeid( Type ),
325 static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
326 static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) )
328 mValue = static_cast< const AnyContainerImpl& >( base ).GetValue();
332 * @brief Get the container's stored value
334 * @return value of type Type
336 const Type& GetValue() const
342 * @brief Set the container's stored value
344 * @param value of type Type
346 void SetValue( const Type& value )
352 * @brief Get a pointer to the value held
354 * @return pointer to the value of type Type
356 Type* GetPointerToValue()
358 return static_cast< Type* >( &mValue );
362 * @brief Get a pointer to the value held
364 * @return pointer to the value of type Type
366 const Type* GetPointerToValue() const
368 return static_cast< const Type* >( &mValue );
375 AnyContainerBase* mContainer;
380 * AnyCast helper functions
384 * @brief Extract a pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
386 * @param any Pointer to an Any object
388 * @return Pointer to the Type held
390 template<typename Type>
391 inline Type* AnyCast( Any* any )
393 return any->GetPointer<Type>();
397 * @brief Extract a const pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
399 * @param any const Pointer to an Any object
401 * @return const Pointer to the Type held
403 template<typename Type>
404 inline const Type* AnyCast( const Any* any )
406 return any->GetPointer<Type>();
410 * @brief Extract a held value of type Type from an Any object from a reference to that Any object
412 * @param any reference to an Any object
414 * @return Type value of type Type
416 template<typename Type>
417 inline Type AnyCast( Any& any )
419 return any.Get<Type>();
423 * @brief Extract a held value of type Type from an Any object from a const reference to that Any object
425 * @param any reference to an Any object
427 * @return Type value of type Type
429 template<typename Type>
430 inline Type AnyCast( const Any& any )
432 return any.Get<Type>();
436 * @brief Extract a reference to the held value of type Type from an Any object from a reference to that Any object
438 * @param any reference to an Any object
440 * @return A reference to the Type value of type Type
442 template<typename Type>
443 inline Type& AnyCastReference( Any& any )
445 return any.Get<Type>();
449 * @brief Extract a const reference to the held value of type Type from an Any object from a const reference to that Any object
451 * @param any reference to an Any object
453 * @return A const reference to the Type value of type Type
455 template<typename Type>
456 inline const Type& AnyCastReference( const Any& any )
458 return any.Get<Type>();
466 #endif // __DALI_ANY_TYPE_H__