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 <dali/public-api/common/dali-common.h>
25 #include <typeinfo> // operator typeid
31 * @brief Stores a value of any type.
35 * Any uintVariable = 5u;
36 * Any floatVariable( 4.5f );
37 * Any strVariable( std::string( "Hello world" ) );
39 * unsigned int variable = AnyCast< unsigned int >( uintVariable );
40 * if ( typeid( int ) == uintVariable.GetType() )
47 * Default constructor.
49 DALI_IMPORT_API Any();
52 * Destructor. Free resources.
54 DALI_IMPORT_API ~Any();
57 * @brief Pass Assert message
59 * @param assertMessage Assert message to report
61 DALI_IMPORT_API static void AssertAlways( const char* assertMessage );
64 * @brief Constructs a Any type with the given value.
66 * @param[in] value The given value.
68 template<typename Type>
69 Any( const Type& value )
70 : mContainer( new AnyContainerImpl<Type>( value ) )
76 * @param [in] any Any to be copied.
80 // If container isn't empty then copy the container?
81 if ( 0 != any.mContainer )
83 mContainer = any.mContainer->mCloneFunc( *any.mContainer );
87 // Otherwise mark new container as empty
93 * @brief Assigns a given value to the Any type.
95 * @note If the types are different, then the current container will be re-created.
97 * @param[in] value The given value.
99 template<typename Type>
100 Any& operator=( const Type& value )
102 // If the container is empty then assign the new value
103 if ( 0 == mContainer )
105 mContainer = new AnyContainerImpl< Type >( value );
109 // Check to see if this type is compatible with current container?
110 if ( mContainer->GetType() == typeid( Type ) )
112 // Same type so just set the new value
113 static_cast< AnyContainerImpl< Type >* >( mContainer )->SetValue( value );
117 // Incompatible types, so delete old container and assign a new one with this type and value
118 mContainer->mDeleteFunc( mContainer );
119 mContainer = new AnyContainerImpl< Type >( value );
126 * @brief Assignment operator.
128 * @exception DaliException If parameter any is of a different type.
130 * @param [in] any Any to be assigned which contains a value of identical type to current contents.
132 DALI_IMPORT_API Any& operator=( const Any& any );
135 * @brief Get a value of type Type from container
137 * @param type destination of type Type to write to
139 template<typename Type>
140 void Get( Type& type ) const
146 * @brief Returns the type info of the stored value.
148 * @return The std::type_info of the stored value or the type info of the void
149 * type if there is no value stored.
151 DALI_IMPORT_API const std::type_info& GetType() const;
154 * @brief Retrieves the stored value in the Any type.
156 * @return The stored value.
158 template<typename Type>
159 const Type& Get() const
162 if ( 0 == mContainer )
164 AssertAlways( "Any::Get(). mContainer is null" );
167 // Check if the value has the same value than the Any type.
168 if( mContainer->GetType() != typeid( Type ) )
170 AssertAlways( "Any::Get(). Trying to retrieve a value of a different type than the template one." );
172 return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetValue();
176 * @brief Return pointer of Type to the value stored
178 * @return pointer to the value or null if no value is contained
180 template<typename Type>
183 if( 0 == mContainer )
187 // Check if the value has the same value than the Any type.
188 if( mContainer->GetType() != typeid( Type ) )
190 AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
192 return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
196 * @brief Return pointer of Type to the value stored
198 * @return pointer to the value or null if no value is contained
200 template<typename Type>
201 const Type* GetPointer() const
203 if( 0 == mContainer )
207 // Check if the value has the same value than the Any type.
208 if( mContainer->GetType() != typeid( Type ) )
210 AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
212 return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
216 * @brief Returns whether container holds a value
218 * @return true if the container is empty, else false.
222 return ( 0 == mContainer ) ? true : false;
225 struct AnyContainerBase; // Forward declaration for typedef
226 typedef AnyContainerBase* (*CloneFunc)( const AnyContainerBase& base );
227 typedef void (*DeleteFunc)( const AnyContainerBase* base );
230 * Base container to hold type for match verification and instance cloning function
233 struct AnyContainerBase
236 * @brief Constructor of base container
238 * @param type typeid of container
239 * @param cloneFunc Cloning function to replicate this container type
240 * @param deleteFunc Deleting function to destroy this container type
242 AnyContainerBase( const std::type_info& type, CloneFunc cloneFunc, DeleteFunc deleteFunc )
244 mCloneFunc( cloneFunc ),
245 mDeleteFunc( deleteFunc )
249 * @brief Get the typeid of this container
253 const std::type_info& GetType() const
258 const::std::type_info& mType; // typeID
259 CloneFunc mCloneFunc; // cloning function for this container
260 DeleteFunc mDeleteFunc; // deleting function for this container
265 * @brief Templated Clone function from container base
267 * @param base reference to container
269 template<typename Type>
270 struct AnyContainerImplCloner
272 static AnyContainerBase* Clone( const AnyContainerBase& base )
274 return new AnyContainerImpl< Type >( static_cast< AnyContainerImpl< Type > >( base ) );
279 * @brief Templated Delete function from container base
281 * @param base pointer to container
283 template<typename Type>
284 struct AnyContainerImplDelete
286 static void Delete( const AnyContainerBase* base )
288 delete ( static_cast< const AnyContainerImpl< Type >* > ( base ) );
293 * @brief Templated class to hold value for type
296 template<typename Type>
297 class AnyContainerImpl : public AnyContainerBase
302 * @brief Constructor to create container holding value of type Type
304 * @param value Value of Type
306 AnyContainerImpl( const Type& value )
307 : AnyContainerBase( typeid( Type ),
308 static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
309 static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) ),
314 * @brief Constructor to create new container of type from and existing container (cloning)
316 * @param base reference to base container to copy from
318 AnyContainerImpl( const AnyContainerBase& base )
319 : AnyContainerBase( typeid( Type ),
320 static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
321 static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) )
323 mValue = static_cast< const AnyContainerImpl& >( base ).GetValue();
327 * @brief Get the container's stored value
329 * @return value of type Type
331 const Type& GetValue() const
337 * @brief Set the container's stored value
339 * @param value of type Type
341 void SetValue( const Type& value )
347 * @brief Get a pointer to the value held
349 * @return pointer to the value of type Type
351 Type* GetPointerToValue()
353 return static_cast< Type* >( &mValue );
357 * @brief Get a pointer to the value held
359 * @return pointer to the value of type Type
361 const Type* GetPointerToValue() const
363 return static_cast< const Type* >( &mValue );
370 AnyContainerBase* mContainer;
375 * AnyCast helper functions
379 * @brief Extract a pointer to the held type of an Any object from a pointer to that Any object (null if empty )
381 * @param any Pointer to an Any object
383 * @return Pointer to the Type held
385 template<typename Type>
386 inline Type* AnyCast( Any* any )
388 return any->GetPointer<Type>();
392 * @brief Extract a const pointer to the held type of an Any object from a pointer to that Any object (null if empty )
394 * @param any const Pointer to an Any object
396 * @return const Pointer to the Type held
398 template<typename Type>
399 inline const Type* AnyCast( const Any* any )
401 return any->GetPointer<Type>();
405 * @brief Extract a held value of type Type from an Any object from a reference to that Any object
407 * @param any reference to an Any object
409 * @return Type value of type Type
411 template<typename Type>
412 inline Type AnyCast( Any& any )
414 return any.Get<Type>();
418 * @brief Extract a held value of type Type from an Any object from a const reference to that Any object
420 * @param any reference to an Any object
422 * @return Type value of type Type
424 template<typename Type>
425 inline Type AnyCast( const Any& any )
427 return any.Get<Type>();
431 * @brief Extract a reference to the held value of type Type from an Any object from a reference to that Any object
433 * @param any reference to an Any object
435 * @return A reference to the Type value of type Type
437 template<typename Type>
438 inline Type& AnyCastReference( Any& any )
440 return any.Get<Type>();
444 * @brief Extract a const reference to the held value of type Type from an Any object from a const reference to that Any object
446 * @param any reference to an Any object
448 * @return A const reference to the Type value of type Type
450 template<typename Type>
451 inline const Type& AnyCastReference( const Any& any )
453 return any.Get<Type>();
458 #endif // __DALI_ANY_TYPE_H__