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