[3.0] Update doxygen tags
[platform/core/uifw/dali-core.git] / dali / public-api / object / any.h
1 #ifndef __DALI_ANY_TYPE_H__
2 #define __DALI_ANY_TYPE_H__
3
4 /*
5  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
6  *
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
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
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 // EXTERNAL INCLUDES
22 #include <typeinfo>   // operator typeid
23 #include <cstddef>    // NULL
24
25 // INTERNAL INCLUDES
26 #include <dali/public-api/common/dali-common.h>
27
28 namespace Dali
29 {
30 /**
31  * @addtogroup dali_core_object
32  * @{
33  */
34
35 /**
36  * @brief Stores a value of any type.
37  *
38  * Examples of use:
39  * \code{.cpp}
40  * Any uintVariable = 5u;
41  * Any floatVariable( 4.5f );
42  * Any strVariable( std::string( "Hello world" ) );
43  * uintVariable = 1u;
44  * unsigned int variable = AnyCast< unsigned int >( uintVariable );
45  * if ( typeid( int ) == uintVariable.GetType() )
46  * \endcode
47  * @SINCE_1_0.0
48  */
49 class Any
50 {
51 public:
52   /**
53    * @brief Default constructor.
54    * @SINCE_1_0.0
55    */
56   DALI_IMPORT_API Any();
57
58   /**
59    * @brief Destructor. Free resources.
60    * @SINCE_1_0.0
61    */
62   DALI_IMPORT_API ~Any();
63
64   /**
65    * @brief Pass Assert message
66    *
67    * @SINCE_1_0.0
68    * @param[in] assertMessage Assert message to report
69    */
70   DALI_IMPORT_API static void AssertAlways( const char* assertMessage );
71
72   /**
73    * @brief Constructs a Any type with the given value.
74    *
75    * @SINCE_1_0.0
76    * @param[in] value The given value.
77    */
78   template<typename Type>
79   Any( const Type& value )
80   : mContainer( new AnyContainerImpl<Type>( value ) )
81   {
82   }
83
84   /**
85    * @brief Copy Constructor.
86    * @SINCE_1_0.0
87    * @param[in] any Any to be copied.
88    */
89   Any( const Any& any )
90   {
91     // If container isn't empty then copy the container?
92     if ( NULL != any.mContainer )
93     {
94       mContainer = any.mContainer->mCloneFunc( *any.mContainer );
95     }
96     else
97     {
98       // Otherwise mark new container as empty
99       mContainer = NULL;
100     }
101   }
102
103   /**
104    * @brief Assigns a given value to the Any type.
105    *
106    * @SINCE_1_0.0
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.
110    *
111    */
112   template<typename Type>
113   Any& operator=( const Type& value )
114   {
115     // If the container is empty then assign the new value
116     if ( NULL == mContainer )
117     {
118       mContainer = new AnyContainerImpl< Type >( value );
119     }
120     else
121     {
122       // Check to see if this type is compatible with current container?
123       if ( mContainer->GetType() == typeid( Type ) )
124       {
125         // Same type so just set the new value
126         static_cast< AnyContainerImpl< Type >* >( mContainer )->SetValue( value );
127       }
128       else
129       {
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 );
133       }
134     }
135     return *this;
136   }
137
138   /**
139    * @brief Assignment operator.
140    *
141    * @SINCE_1_0.0
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.
145    *
146    */
147   DALI_IMPORT_API Any& operator=( const Any& any );
148
149   /**
150    * @brief Get a value of type Type from container
151    *
152    * @SINCE_1_0.0
153    * @param[in] type destination of type Type to write to
154    */
155   template<typename Type>
156   void Get( Type& type ) const
157   {
158     type = Get<Type>();
159   }
160
161   /**
162    * @brief Returns the type info of the stored value.
163    *
164    * @SINCE_1_0.0
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.
167    */
168   DALI_IMPORT_API const std::type_info& GetType() const;
169
170   /**
171    * @brief Retrieves the stored value in the Any type.
172    *
173    * @SINCE_1_0.0
174    * @return The stored value.
175    */
176   template<typename Type>
177   const Type& Get() const
178   {
179
180     if ( NULL == mContainer )
181     {
182       AssertAlways( "Any::Get(). mContainer is NULL" );
183     }
184
185     // Check if the value has the same value than the Any type.
186     if( mContainer->GetType() != typeid( Type ) )
187     {
188       AssertAlways( "Any::Get(). Trying to retrieve a value of a different type than the template one." );
189     }
190     return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetValue();
191   }
192
193   /**
194    * @brief Return pointer of Type to the value stored
195    *
196    * @SINCE_1_0.0
197    * @return pointer to the value or NULL if no value is contained
198    */
199   template<typename Type>
200   Type* GetPointer()
201   {
202     if( NULL == mContainer )
203     {
204       return NULL;
205     }
206      // Check if the value has the same value than the Any type.
207     if( mContainer->GetType() != typeid( Type ) )
208     {
209       AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
210     }
211     return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
212   }
213
214   /**
215    * @brief Return pointer of Type to the value stored
216    *
217    * @SINCE_1_0.0
218    * @return pointer to the value or NULL if no value is contained
219    */
220   template<typename Type>
221   const Type* GetPointer() const
222   {
223     if( NULL == mContainer )
224     {
225       return NULL;
226     }
227      // Check if the value has the same value than the Any type.
228     if( mContainer->GetType() != typeid( Type ) )
229     {
230       AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
231     }
232     return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
233   }
234
235   /**
236    * @brief Returns whether container holds a value
237    *
238    * @SINCE_1_0.0
239    * @return true if the container is empty, else false.
240    */
241   bool Empty() const
242   {
243     return ( NULL == mContainer ) ? true : false;
244   }
245
246   struct AnyContainerBase;    // Forward declaration for typedef
247   typedef AnyContainerBase* (*CloneFunc)( const AnyContainerBase& base );
248   typedef void (*DeleteFunc)( const AnyContainerBase* base );
249
250   /**
251    * @brief Base container to hold type for match verification and instance cloning function
252    *
253    * @SINCE_1_0.0
254    */
255   struct AnyContainerBase
256   {
257     /**
258      * @brief Constructor of base container
259      *
260      * @SINCE_1_0.0
261      * @param[in] type typeid of container
262      * @param[in] cloneFunc Cloning function to replicate this container type
263      * @param[in] deleteFunc Deleting function to destroy this container type
264      */
265     AnyContainerBase( const std::type_info& type, CloneFunc cloneFunc, DeleteFunc deleteFunc )
266     : mType( type ),
267       mCloneFunc( cloneFunc ),
268       mDeleteFunc( deleteFunc )
269     {}
270
271     /**
272      * @brief Get the typeid of this container
273      *
274      * @SINCE_1_0.0
275      * @return type
276      */
277     const std::type_info& GetType() const
278     {
279       return mType;
280     }
281
282     const::std::type_info& mType;       // typeID
283     CloneFunc mCloneFunc;               // cloning function for this container
284     DeleteFunc mDeleteFunc;             // deleting function for this container
285   };
286
287
288   /**
289    * @brief Templated Clone function from container base
290    *
291    * @SINCE_1_0.0
292    * @param[in] base reference to container
293    */
294   template<typename Type>
295   struct AnyContainerImplCloner
296   {
297     static AnyContainerBase* Clone( const AnyContainerBase& base )
298     {
299       return new AnyContainerImpl< Type >( static_cast< AnyContainerImpl< Type > >( base ) );
300     }
301   };
302
303   /**
304    * @brief Templated Delete function from container base
305    *
306    * @SINCE_1_0.0
307    * @param[in] base pointer to container
308    */
309   template<typename Type>
310   struct AnyContainerImplDelete
311   {
312     static void Delete( const AnyContainerBase* base )
313     {
314       delete ( static_cast< const AnyContainerImpl< Type >* > ( base ) );
315     }
316   };
317
318   /**
319    * @brief Templated class to hold value for type
320    *
321    * @SINCE_1_0.0
322    */
323   template<typename Type>
324   class AnyContainerImpl : public AnyContainerBase
325   {
326   public:
327
328     /**
329      * @brief Constructor to create container holding value of type Type
330      *
331      * @SINCE_1_0.0
332      * @param[in] value Value of Type
333      */
334     AnyContainerImpl( const Type& value )
335     : AnyContainerBase( typeid( Type ),
336                         static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
337                         static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) ),
338                         mValue( value )
339     {}
340
341     /**
342      * @brief Constructor to create new container of type from and existing container (cloning)
343      *
344      * @SINCE_1_0.0
345      * @param[in] base reference to base container to copy from
346      */
347     AnyContainerImpl( const AnyContainerBase& base )
348     : AnyContainerBase( typeid( Type ),
349                         static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
350                         static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) )
351     {
352       mValue = static_cast< const AnyContainerImpl& >( base ).GetValue();
353     }
354
355     /**
356      * @brief Get the container's stored value
357      *
358      * @SINCE_1_0.0
359      * @return value of type Type
360      */
361     const Type& GetValue() const
362     {
363       return mValue;
364     }
365
366     /**
367      * @brief Set the container's stored value
368      *
369      * @SINCE_1_0.0
370      * @param[in] value of type Type
371      */
372     void SetValue( const Type& value )
373     {
374       mValue = value;
375     }
376
377     /**
378      * @brief Get a pointer to the value held
379      *
380      * @SINCE_1_0.0
381      * @return pointer to the value of type Type
382      */
383     Type* GetPointerToValue()
384     {
385       return static_cast< Type* >( &mValue );
386     }
387
388     /**
389      * @brief Get a pointer to the value held
390      *
391      * @SINCE_1_0.0
392      * @return pointer to the value of type Type
393      */
394     const Type* GetPointerToValue() const
395     {
396       return static_cast< const Type* >( &mValue );
397     }
398
399     private:
400       Type mValue;
401   };
402
403   AnyContainerBase* mContainer;
404
405 };
406
407 /**
408  * AnyCast helper functions
409  */
410
411 /**
412  * @brief Extract a pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
413  *
414  * @SINCE_1_0.0
415  * @param[in] any Pointer to an Any object
416  *
417  * @return Pointer to the Type held
418  */
419 template<typename Type>
420 inline Type* AnyCast( Any* any )
421 {
422   return any->GetPointer<Type>();
423 }
424
425 /**
426  * @brief Extract a const pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
427  *
428  * @SINCE_1_0.0
429  * @param[in] any const Pointer to an Any object
430  *
431  * @return const Pointer to the Type held
432  */
433 template<typename Type>
434 inline const Type* AnyCast( const Any* any )
435 {
436   return any->GetPointer<Type>();
437 }
438
439 /**
440  * @brief Extract a held value of type Type from an Any object from a reference to that Any object
441  *
442  * @SINCE_1_0.0
443  * @param[in] any reference to an Any object
444  *
445  * @return Type value of type Type
446  */
447 template<typename Type>
448 inline Type AnyCast( Any& any )
449 {
450   return any.Get<Type>();
451 }
452
453 /**
454  * @brief Extract a held value of type Type from an Any object from a const reference to that Any object
455  *
456  * @SINCE_1_0.0
457  * @param[in] any reference to an Any object
458  *
459  * @return Type value of type Type
460  */
461 template<typename Type>
462 inline Type AnyCast( const Any& any )
463 {
464   return any.Get<Type>();
465 }
466
467 /**
468  * @brief Extract a reference to the held value of type Type from an Any object from a reference to that Any object
469  *
470  * @SINCE_1_0.0
471  * @param[in] any reference to an Any object
472  *
473  * @return A reference to the Type value of type Type
474  */
475 template<typename Type>
476 inline Type& AnyCastReference( Any& any )
477 {
478   return any.Get<Type>();
479 }
480
481 /**
482  * @brief Extract a const reference to the held value of type Type from an Any object from a const reference to that Any object
483  *
484  * @SINCE_1_0.0
485  * @param[in] any reference to an Any object
486  *
487  * @return A const reference to the Type value of type Type
488  */
489 template<typename Type>
490 inline const Type& AnyCastReference( const Any& any )
491 {
492   return any.Get<Type>();
493 }
494
495 /**
496  * @}
497  */
498 } // namespace Dali
499
500 #endif // __DALI_ANY_TYPE_H__