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