Merge "Prevents an invalid texture cache being interrogated for a texture. This ...
[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  */
48 class Any
49 {
50 public:
51   /**
52    * Default constructor.
53    */
54   DALI_IMPORT_API Any();
55
56   /**
57    * Destructor. Free resources.
58    */
59   DALI_IMPORT_API ~Any();
60
61   /**
62    * @brief Pass Assert message
63    *
64    * @param assertMessage Assert message to report
65    */
66   DALI_IMPORT_API static void AssertAlways( const char* assertMessage );
67
68   /**
69    * @brief Constructs a Any type with the given value.
70    *
71    * @param[in] value The given value.
72    */
73   template<typename Type>
74   Any( const Type& value )
75   : mContainer( new AnyContainerImpl<Type>( value ) )
76   {
77   }
78
79   /**
80    * Copy Constructor.
81    * @param [in] any Any to be copied.
82    */
83   Any( const Any& any )
84   {
85     // If container isn't empty then copy the container?
86     if ( NULL != any.mContainer )
87     {
88       mContainer = any.mContainer->mCloneFunc( *any.mContainer );
89     }
90     else
91     {
92       // Otherwise mark new container as empty
93       mContainer = NULL;
94     }
95   }
96
97   /**
98    * @brief Assigns a given value to the Any type.
99    *
100    * @note If the types are different, then the current container will be re-created.
101    *
102    * @param[in] value The given value.
103    */
104   template<typename Type>
105   Any& operator=( const Type& value )
106   {
107     // If the container is empty then assign the new value
108     if ( NULL == mContainer )
109     {
110       mContainer = new AnyContainerImpl< Type >( value );
111     }
112     else
113     {
114       // Check to see if this type is compatible with current container?
115       if ( mContainer->GetType() == typeid( Type ) )
116       {
117         // Same type so just set the new value
118         static_cast< AnyContainerImpl< Type >* >( mContainer )->SetValue( value );
119       }
120       else
121       {
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 );
125       }
126     }
127     return *this;
128   }
129
130   /**
131    * @brief Assignment operator.
132    *
133    * @exception DaliException If parameter any is of a different type.
134    *
135    * @param [in] any Any to be assigned which contains a value of identical type to current contents.
136    */
137   DALI_IMPORT_API Any& operator=( const Any& any );
138
139   /**
140    * @brief Get a value of type Type from container
141    *
142    * @param type destination of type Type to write to
143    */
144   template<typename Type>
145   void Get( Type& type ) const
146   {
147     type = Get<Type>();
148   }
149
150   /**
151    * @brief Returns the type info of the stored value.
152    *
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.
155    */
156   DALI_IMPORT_API const std::type_info& GetType() const;
157
158   /**
159    * @brief Retrieves the stored value in the Any type.
160    *
161    * @return The stored value.
162    */
163   template<typename Type>
164   const Type& Get() const
165   {
166
167     if ( NULL == mContainer )
168     {
169       AssertAlways( "Any::Get(). mContainer is NULL" );
170     }
171
172     // Check if the value has the same value than the Any type.
173     if( mContainer->GetType() != typeid( Type ) )
174     {
175       AssertAlways( "Any::Get(). Trying to retrieve a value of a different type than the template one." );
176     }
177     return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetValue();
178   }
179
180   /**
181    * @brief Return pointer of Type to the value stored
182    *
183    * @return pointer to the value or NULL if no value is contained
184    */
185   template<typename Type>
186   Type* GetPointer()
187   {
188     if( NULL == mContainer )
189     {
190       return NULL;
191     }
192      // Check if the value has the same value than the Any type.
193     if( mContainer->GetType() != typeid( Type ) )
194     {
195       AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
196     }
197     return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
198   }
199
200   /**
201    * @brief Return pointer of Type to the value stored
202    *
203    * @return pointer to the value or NULL if no value is contained
204    */
205   template<typename Type>
206   const Type* GetPointer() const
207   {
208     if( NULL == mContainer )
209     {
210       return NULL;
211     }
212      // Check if the value has the same value than the Any type.
213     if( mContainer->GetType() != typeid( Type ) )
214     {
215       AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
216     }
217     return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
218   }
219
220   /**
221    * @brief Returns whether container holds a value
222    *
223    * @return true if the container is empty, else false.
224    */
225   bool Empty() const
226   {
227     return ( NULL == mContainer ) ? true : false;
228   }
229
230   struct AnyContainerBase;    // Forward declaration for typedef
231   typedef AnyContainerBase* (*CloneFunc)( const AnyContainerBase& base );
232   typedef void (*DeleteFunc)( const AnyContainerBase* base );
233
234   /**
235    * Base container to hold type for match verification and instance cloning function
236    *
237    */
238   struct AnyContainerBase
239   {
240     /**
241      * @brief Constructor of base container
242      *
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
246      */
247     AnyContainerBase( const std::type_info& type, CloneFunc cloneFunc, DeleteFunc deleteFunc )
248     : mType( type ),
249       mCloneFunc( cloneFunc ),
250       mDeleteFunc( deleteFunc )
251     {}
252
253     /**
254      * @brief Get the typeid of this container
255      *
256      * @return type
257      */
258     const std::type_info& GetType() const
259     {
260       return mType;
261     }
262
263     const::std::type_info& mType;       // typeID
264     CloneFunc mCloneFunc;               // cloning function for this container
265     DeleteFunc mDeleteFunc;             // deleting function for this container
266   };
267
268
269   /**
270    * @brief Templated Clone function from container base
271    *
272    * @param base reference to container
273    */
274   template<typename Type>
275   struct AnyContainerImplCloner
276   {
277     static AnyContainerBase* Clone( const AnyContainerBase& base )
278     {
279       return new AnyContainerImpl< Type >( static_cast< AnyContainerImpl< Type > >( base ) );
280     }
281   };
282
283   /**
284    * @brief Templated Delete function from container base
285    *
286    * @param base pointer to container
287    */
288   template<typename Type>
289   struct AnyContainerImplDelete
290   {
291     static void Delete( const AnyContainerBase* base )
292     {
293       delete ( static_cast< const AnyContainerImpl< Type >* > ( base ) );
294     }
295   };
296
297   /**
298    * @brief Templated class to hold value for type
299    *
300    */
301   template<typename Type>
302   class AnyContainerImpl : public AnyContainerBase
303   {
304   public:
305
306     /**
307      * @brief Constructor to create container holding value of type Type
308      *
309      * @param value Value of Type
310      */
311     AnyContainerImpl( const Type& value )
312     : AnyContainerBase( typeid( Type ),
313                         static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
314                         static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) ),
315                         mValue( value )
316     {}
317
318     /**
319      * @brief Constructor to create new container of type from and existing container (cloning)
320      *
321      * @param base reference to base container to copy from
322      */
323     AnyContainerImpl( const AnyContainerBase& base )
324     : AnyContainerBase( typeid( Type ),
325                         static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
326                         static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) )
327     {
328       mValue = static_cast< const AnyContainerImpl& >( base ).GetValue();
329     }
330
331     /**
332      * @brief Get the container's stored value
333      *
334      * @return value of type Type
335      */
336     const Type& GetValue() const
337     {
338       return mValue;
339     }
340
341     /**
342      * @brief Set the container's stored value
343      *
344      * @param value of type Type
345      */
346     void SetValue( const Type& value )
347     {
348       mValue = value;
349     }
350
351     /**
352      * @brief Get a pointer to the value held
353      *
354      * @return pointer to the value of type Type
355      */
356     Type* GetPointerToValue()
357     {
358       return static_cast< Type* >( &mValue );
359     }
360
361     /**
362      * @brief Get a pointer to the value held
363      *
364      * @return pointer to the value of type Type
365      */
366     const Type* GetPointerToValue() const
367     {
368       return static_cast< const Type* >( &mValue );
369     }
370
371     private:
372       Type mValue;
373   };
374
375   AnyContainerBase* mContainer;
376
377 };
378
379 /**
380  * AnyCast helper functions
381  */
382
383 /**
384  * @brief Extract a pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
385  *
386  * @param any Pointer to an Any object
387  *
388  * @return Pointer to the Type held
389  */
390 template<typename Type>
391 inline Type* AnyCast( Any* any )
392 {
393   return any->GetPointer<Type>();
394 }
395
396 /**
397  * @brief Extract a const pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
398  *
399  * @param any const Pointer to an Any object
400  *
401  * @return const Pointer to the Type held
402  */
403 template<typename Type>
404 inline const Type* AnyCast( const Any* any )
405 {
406   return any->GetPointer<Type>();
407 }
408
409 /**
410  * @brief Extract a held value of type Type from an Any object from a reference to that Any object
411  *
412  * @param any reference to an Any object
413  *
414  * @return Type value of type Type
415  */
416 template<typename Type>
417 inline Type AnyCast( Any& any )
418 {
419   return any.Get<Type>();
420 }
421
422 /**
423  * @brief Extract a held value of type Type from an Any object from a const reference to that Any object
424  *
425  * @param any reference to an Any object
426  *
427  * @return Type value of type Type
428  */
429 template<typename Type>
430 inline Type AnyCast( const Any& any )
431 {
432   return any.Get<Type>();
433 }
434
435 /**
436  * @brief Extract a reference to the held value of type Type from an Any object from a reference to that Any object
437  *
438  * @param any reference to an Any object
439  *
440  * @return A reference to the Type value of type Type
441  */
442 template<typename Type>
443 inline Type& AnyCastReference( Any& any )
444 {
445   return any.Get<Type>();
446 }
447
448 /**
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
450  *
451  * @param any reference to an Any object
452  *
453  * @return A const reference to the Type value of type Type
454  */
455 template<typename Type>
456 inline const Type& AnyCastReference( const Any& any )
457 {
458   return any.Get<Type>();
459 }
460
461 /**
462  * @}
463  */
464 } // namespace Dali
465
466 #endif // __DALI_ANY_TYPE_H__