0dbf3253af1a6c5545e047fa3b7ad95d6e26d436
[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) 2019 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  * uint32_t variable = AnyCast< uint32_t >( 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_CORE_API Any();
57
58   /**
59    * @brief Destructor. Free resources.
60    * @SINCE_1_0.0
61    */
62   DALI_CORE_API ~Any();
63
64   /**
65    * @brief Passes Assert message.
66    *
67    * @SINCE_1_0.0
68    * @param[in] assertMessage Assert message to report
69    */
70   DALI_CORE_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_CORE_API Any& operator=( const Any& any );
148
149   /**
150    * @brief Gets 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_CORE_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     if ( NULL == mContainer )
180     {
181       AssertAlways( "Any::Get(). mContainer is NULL" );
182     }
183     else if( mContainer->GetType() != typeid( Type ) ) // Check if the value has the same value than the Any type.
184     {
185       AssertAlways( "Any::Get(). Trying to retrieve a value of a different type than the template one." );
186       return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetValue();
187     }
188     return NULL;
189   }
190
191   /**
192    * @brief Returns pointer of Type to the value stored.
193    *
194    * @SINCE_1_0.0
195    * @return pointer to the value, or NULL if no value is contained
196    */
197   template<typename Type>
198   Type* GetPointer()
199   {
200     if( NULL == mContainer )
201     {
202       return NULL;
203     }
204      // Check if the value has the same value than the Any type.
205     if( mContainer->GetType() != typeid( Type ) )
206     {
207       AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
208     }
209     return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
210   }
211
212   /**
213    * @brief Returns pointer of Type to the value stored.
214    *
215    * @SINCE_1_0.0
216    * @return pointer to the value, or NULL if no value is contained
217    */
218   template<typename Type>
219   const Type* GetPointer() const
220   {
221     if( NULL == mContainer )
222     {
223       return NULL;
224     }
225      // Check if the value has the same value than the Any type.
226     if( mContainer->GetType() != typeid( Type ) )
227     {
228       AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
229     }
230     return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
231   }
232
233   /**
234    * @brief Returns whether container holds a value.
235    *
236    * @SINCE_1_0.0
237    * @return @c true if the container is empty, else @c false
238    */
239   bool Empty() const
240   {
241     return ( NULL == mContainer ) ? true : false;
242   }
243
244   struct AnyContainerBase;    // Forward declaration for typedef
245   typedef AnyContainerBase* (*CloneFunc)( const AnyContainerBase& base );
246   typedef void (*DeleteFunc)( const AnyContainerBase* base );
247
248   /**
249    * @brief Base container to hold type for match verification and instance cloning function.
250    *
251    * @SINCE_1_0.0
252    */
253   struct AnyContainerBase
254   {
255     /**
256      * @brief Constructor of base container.
257      *
258      * @SINCE_1_0.0
259      * @param[in] type typeid of container
260      * @param[in] cloneFunc Cloning function to replicate this container type
261      * @param[in] deleteFunc Deleting function to destroy this container type
262      */
263     AnyContainerBase( const std::type_info& type, CloneFunc cloneFunc, DeleteFunc deleteFunc )
264     : mType( type ),
265       mCloneFunc( cloneFunc ),
266       mDeleteFunc( deleteFunc )
267     {}
268
269     /**
270      * @brief Gets the typeid of this container.
271      *
272      * @SINCE_1_0.0
273      * @return Type
274      */
275     const std::type_info& GetType() const
276     {
277       return mType;
278     }
279
280     const::std::type_info& mType;       // typeID
281     CloneFunc mCloneFunc;               // cloning function for this container
282     DeleteFunc mDeleteFunc;             // deleting function for this container
283   };
284
285
286   /**
287    * @brief Templated Clone function from container base.
288    *
289    * @SINCE_1_0.0
290    * @param[in] base The reference to container
291    */
292   template<typename Type>
293   struct AnyContainerImplCloner
294   {
295     static AnyContainerBase* Clone( const AnyContainerBase& base )
296     {
297       return new AnyContainerImpl< Type >( static_cast< AnyContainerImpl< Type > >( base ) );
298     }
299   };
300
301   /**
302    * @brief Templated Delete function from container base.
303    *
304    * @SINCE_1_0.0
305    * @param[in] base The pointer to container
306    */
307   template<typename Type>
308   struct AnyContainerImplDelete
309   {
310     static void Delete( const AnyContainerBase* base )
311     {
312       delete ( static_cast< const AnyContainerImpl< Type >* > ( base ) );
313     }
314   };
315
316   /**
317    * @brief Templated class to hold value for type.
318    *
319    * @SINCE_1_0.0
320    */
321   template<typename Type>
322   class AnyContainerImpl : public AnyContainerBase
323   {
324   public:
325
326     /**
327      * @brief Constructor to create container holding value of type Type.
328      *
329      * @SINCE_1_0.0
330      * @param[in] value Value of Type
331      */
332     AnyContainerImpl( const Type& value )
333     : AnyContainerBase( typeid( Type ),
334                         static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
335                         static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) ),
336                         mValue( value )
337     {}
338
339     /**
340      * @brief Constructor to create new container of type from and existing container (cloning).
341      *
342      * @SINCE_1_0.0
343      * @param[in] base The reference to base container to copy from
344      */
345     AnyContainerImpl( const AnyContainerBase& base )
346     : AnyContainerBase( typeid( Type ),
347                         static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
348                         static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) )
349     {
350       mValue = static_cast< const AnyContainerImpl& >( base ).GetValue();
351     }
352
353     /**
354      * @brief Gets the container's stored value.
355      *
356      * @SINCE_1_0.0
357      * @return Value of type Type
358      */
359     const Type& GetValue() const
360     {
361       return mValue;
362     }
363
364     /**
365      * @brief Sets the container's stored value.
366      *
367      * @SINCE_1_0.0
368      * @param[in] value Value of type Type
369      */
370     void SetValue( const Type& value )
371     {
372       mValue = value;
373     }
374
375     /**
376      * @brief Gets a pointer to the value held.
377      *
378      * @SINCE_1_0.0
379      * @return Pointer to the value of type Type
380      */
381     Type* GetPointerToValue()
382     {
383       return static_cast< Type* >( &mValue );
384     }
385
386     /**
387      * @brief Gets a pointer to the value held.
388      *
389      * @SINCE_1_0.0
390      * @return Pointer to the value of type Type
391      */
392     const Type* GetPointerToValue() const
393     {
394       return static_cast< const Type* >( &mValue );
395     }
396
397     private:
398       Type mValue;
399   };
400
401   AnyContainerBase* mContainer;
402
403 };
404
405 /**
406  * AnyCast helper functions
407  */
408
409 /**
410  * @brief Extracts a pointer to the held type of an Any object from a pointer to that Any object (NULL if empty).
411  *
412  * @SINCE_1_0.0
413  * @param[in] any Pointer to an Any object
414  *
415  * @return Pointer to the Type held
416  */
417 template<typename Type>
418 inline Type* AnyCast( Any* any )
419 {
420   return any->GetPointer<Type>();
421 }
422
423 /**
424  * @brief Extracts a const pointer to the held type of an Any object from a pointer to that Any object (NULL if empty).
425  *
426  * @SINCE_1_0.0
427  * @param[in] any const Pointer to an Any object
428  *
429  * @return const Pointer to the Type held
430  */
431 template<typename Type>
432 inline const Type* AnyCast( const Any* any )
433 {
434   return any->GetPointer<Type>();
435 }
436
437 /**
438  * @brief Extracts a held value of type Type from an Any object from a reference to that Any object.
439  *
440  * @SINCE_1_0.0
441  * @param[in] any The reference to an Any object
442  *
443  * @return Type value of type Type
444  */
445 template<typename Type>
446 inline Type AnyCast( Any& any )
447 {
448   return any.Get<Type>();
449 }
450
451 /**
452  * @brief Extracts a held value of type Type from an Any object from a const reference to that Any object.
453  *
454  * @SINCE_1_0.0
455  * @param[in] any The reference to an Any object
456  *
457  * @return Type value of type Type
458  */
459 template<typename Type>
460 inline Type AnyCast( const Any& any )
461 {
462   return any.Get<Type>();
463 }
464
465 /**
466  * @brief Extracts a reference to the held value of type Type from an Any object from a reference to that Any object
467  *
468  * @SINCE_1_0.0
469  * @param[in] any The reference to an Any object
470  *
471  * @return A reference to the Type value of type Type
472  */
473 template<typename Type>
474 inline Type& AnyCastReference( Any& any )
475 {
476   return any.Get<Type>();
477 }
478
479 /**
480  * @brief Extracts a const reference to the held value of type Type from an Any object from a const reference to that Any object.
481  *
482  * @SINCE_1_0.0
483  * @param[in] any The reference to an Any object
484  *
485  * @return A const reference to the Type value of type Type
486  */
487 template<typename Type>
488 inline const Type& AnyCastReference( const Any& any )
489 {
490   return any.Get<Type>();
491 }
492
493 /**
494  * @}
495  */
496 } // namespace Dali
497
498 #endif // DALI_ANY_TYPE_H