2f49a2143d4091e6304449df3efba1315431aa27
[platform/core/uifw/dali-core.git] / capi / dali / public-api / object / any.h
1 #ifndef __DALI_ANY_TYPE_H__
2 #define __DALI_ANY_TYPE_H__
3
4 //
5 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
6 //
7 // Licensed under the Flora License, Version 1.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
10 //
11 //     http://floralicense.org/license/
12 //
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.
18 //
19
20 /**
21  * @addtogroup CAPI_DALI_OBJECT_MODULE
22  * @{
23  */
24
25 // EXTERNAL INCLUDES
26 #include <typeinfo>   // operator typeid
27
28
29 // INTERNAL INCLUDES
30 #include <dali/public-api/common/dali-common.h>
31
32 namespace Dali DALI_IMPORT_API
33 {
34
35 /**
36  * Stores a value of any type.
37  *
38  * @note Assignments of values with different types are now allowed to replicate Any behaviour
39  *
40  * Examples of use:
41  * \code{.cpp}
42  * Any uintVariable = 5u;
43  * Any floatVariable( 4.5f );
44  * Any strVariable( std::string( "Hello world" ) );
45  * uintVariable = 1u;
46  * unsigned int variable = AnyCast< unsigned int >( uintVariable );
47  * if ( typeid( int ) == uintVariable.GetType() )
48  * \endcode
49  */
50 class Any
51 {
52 public:
53   /**
54    * Default constructor.
55    */
56   Any();
57
58   /**
59    * Destructor. Free resources.
60    */
61   ~Any();
62
63 /**
64    * @brief Pass Assert message
65    *
66    * @param assertMessage Assert message to report
67    */
68   static void AssertAlways( const char* assertMessage );
69
70   /**
71    * @brief Constructs a Any type with the given value.
72    *
73    * @param[in] value The given value.
74    */
75   template<typename Type>
76   Any( const Type& value )
77   : mContainer( new AnyContainerImpl<Type>( value ) )
78   {
79   }
80
81   /**
82    * Copy Constructor.
83    * @param [in] any Any to be copied.
84    */
85   Any( const Any& any )
86   {
87     // If container isn't empty then copy the container?
88     if ( NULL != any.mContainer )
89     {
90       mContainer = any.mContainer->mCloneFunc( *any.mContainer );
91     }
92     else
93     {
94       // Otherwise mark new container as empty
95       mContainer = NULL;
96     }
97   }
98
99   /**
100    * @brief Assigns a given value to the Any type.
101    *
102    * @note If the types are different, then the current container will be re-created.
103    *
104    * @param[in] value The given value.
105    */
106   template<typename Type>
107   Any& operator=( const Type& value )
108   {
109
110     // If the container is empty then assign the new value
111     if ( NULL == mContainer )
112     {
113       mContainer = new AnyContainerImpl< Type >( value );
114     }
115     else
116     {
117       // Check to see if this type is compatible with current container?
118       if ( mContainer->GetType() == typeid( Type ) )
119       {
120         // Same type so just set the new value
121         static_cast< AnyContainerImpl< Type >* >( mContainer )->SetValue( value );
122       }
123       else
124       {
125         // Incompatible types, so delete old container and assign a new one with this type and value
126         mContainer->mDeleteFunc( mContainer );
127         mContainer = new AnyContainerImpl< Type >( value );
128       }
129     }
130     return *this;
131   }
132
133   /**
134    * @brief Assignment operator.
135    *
136    * @note Asserts if values of different types are assigned.
137    *
138    * @param [in] any Any to be assigned.
139    */
140   Any& operator=( const Any& any );
141
142   /**
143    * @brief Get a value of type Type from container
144    *
145    * @param type destination of type Type to write to
146    */
147   template<typename Type>
148   void Get( Type& type )
149   {
150     type = Get<Type>();
151   }
152
153   /**
154    * @brief Returns the type info of the stored value.
155    *
156    * @note Returns the info of the void type if there is no value stored.
157    */
158   const std::type_info& GetType() const;
159
160   /**
161    * @brief Retrieves the stored value in the Any type.
162    *
163    * @return The stored value.
164    */
165   template<typename Type>
166   const Type& Get() const
167   {
168
169     if ( NULL == mContainer )
170     {
171       AssertAlways( "Any::Get(). mContainer is NULL" );
172     }
173
174     // Check if the value has the same value than the Any type.
175     if( mContainer->GetType() != typeid( Type ) )
176     {
177       AssertAlways( "Any::Get(). Trying to retrieve a value of a different type than the template one." );
178     }
179     return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetValue();
180   }
181
182   /**
183    * @brief Return pointer of Type to the value stored
184    *
185    * @return pointer to the value or NULL if no value is contained
186    */
187   template<typename Type>
188   Type* GetPointer()
189   {
190     if( NULL == mContainer )
191     {
192       return NULL;
193     }
194      // Check if the value has the same value than the Any type.
195     if( mContainer->GetType() != typeid( Type ) )
196     {
197       AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
198     }
199     return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
200   }
201
202   /**
203    * @brief Returns whether container holds a value
204    *
205    * @return true or false
206    */
207   bool Empty()
208   {
209     return ( NULL == mContainer ) ? true : false;
210   }
211
212   struct AnyContainerBase;    // Forward declaration for typedef
213   typedef AnyContainerBase* (*CloneFunc)( const AnyContainerBase& base );
214   typedef void (*DeleteFunc)( const AnyContainerBase* base );
215
216   /**
217    * Base container to hold type for match verification and instance cloning function
218    *
219    */
220   struct AnyContainerBase
221   {
222     /**
223      * @brief Constructor of base container
224      *
225      * @param type typeid of container
226      * @param cloneFunc Cloning function to replicate this container type
227      * @param deleteFunc Deleting function to destroy this container type
228      */
229     AnyContainerBase( const std::type_info& type, CloneFunc cloneFunc, DeleteFunc deleteFunc )
230     : mType( type ),
231       mCloneFunc( cloneFunc ),
232       mDeleteFunc( deleteFunc )
233     {}
234
235     /**
236      * @brief Get the typeid of this container
237      *
238      * @return type
239      */
240     const std::type_info& GetType() const
241     {
242       return mType;
243     }
244
245     const::std::type_info& mType;       // typeID
246     CloneFunc mCloneFunc;               // cloning function for this container
247     DeleteFunc mDeleteFunc;             // deleting function for this container
248   };
249
250
251   /**
252    * @brief Templated Clone function from container base
253    *
254    * @param base reference to container
255    */
256   template<typename Type>
257   struct AnyContainerImplCloner
258   {
259     static AnyContainerBase* Clone( const AnyContainerBase& base )
260     {
261       return new AnyContainerImpl< Type >( static_cast< AnyContainerImpl< Type > >( base ) );
262     }
263   };
264
265   /**
266    * @brief Templated Delete function from container base
267    *
268    * @param base pointer to container
269    */
270   template<typename Type>
271   struct AnyContainerImplDelete
272   {
273     static void Delete( const AnyContainerBase* base )
274     {
275       delete ( static_cast< const AnyContainerImpl< Type >* > ( base ) );
276     }
277   };
278
279   /**
280    * @brief Templated class to hold value for type
281    *
282    */
283   template<typename Type>
284   class AnyContainerImpl : public AnyContainerBase
285   {
286   public:
287
288     /**
289      * @brief Constructor to create container holding value of type Type
290      *
291      * @param value Value of Type
292      */
293     AnyContainerImpl( const Type& value )
294     : AnyContainerBase( typeid( Type ),
295                         static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
296                         static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) ),
297                         mValue( value )
298     {}
299
300     /**
301      * @brief Constructor to create new container of type from and existing container (cloning)
302      *
303      * @param base reference to base container to copy from
304      */
305     AnyContainerImpl( const AnyContainerBase& base )
306     : AnyContainerBase( typeid( Type ),
307                         static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
308                         static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) )
309     {
310       mValue = static_cast< const AnyContainerImpl& >( base ).GetValue();
311     }
312
313     /**
314      * @brief Get the container's stored value
315      *
316      * @return value of Type
317      */
318     const Type& GetValue() const
319     {
320       return mValue;
321     }
322
323     void SetValue( const Type& value )
324     {
325       mValue = value;
326     }
327
328     /**
329      * @brief Get a pointer to the value held
330      *
331      * @return pointer to the value of type Type
332      */
333     Type* GetPointerToValue()
334     {
335       return static_cast< Type* >( &mValue );
336     }
337
338     private:
339       Type mValue;
340   };
341
342   AnyContainerBase* mContainer;
343
344 };
345
346 /**
347  * AnyCast helper functions ( replicates boost functionality, but without exception generation )
348  */
349
350 /**
351  * @brief Extract a pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
352  *
353  * @param any Pointer to an Any object
354  *
355  * @return Pointer to the Type held
356  */
357 template<typename Type>inline Type* AnyCast( Any* any )
358 {
359   return any->GetPointer<Type>();
360 }
361
362 /**
363  * @brief Extract a const pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
364  *
365  * @param any const Pointer to an Any object
366  *
367  * @return const Pointer to the Type held
368  */
369 template<typename Type>inline const Type* AnyCast( const Any* any )
370 {
371   return any->GetPointer<Type>();
372 }
373
374 /**
375  * @brief Extract a held value of type Type from an Any object from a reference to that Any object
376  *
377  * @param any reference to an Any object
378  *
379  * @return Type value of type Type
380  */
381 template<typename Type>inline Type AnyCast( Any& any )
382 {
383   return any.Get<Type>();
384 }
385
386 /**
387  * @brief Extract a held value of type Type from an Any object from a const reference to that Any object
388  *
389  * @param any reference to an Any object
390  *
391  * @return Type value of type Type
392  */
393 template<typename Type>inline Type AnyCast( const Any& any )
394 {
395   return any.Get<Type>();
396 }
397
398 } // namespace Dali
399
400 /**
401  * @}
402  */
403 #endif // __DALI_ANY_TYPE_H__