Boost::any replacement in Dali Core functions
[platform/core/uifw/dali-core.git] / capi / 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 Flora License, Version 1.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://floralicense.org/license/
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  * @addtogroup CAPI_DALI_OBJECT_MODULE
22  * @{
23  */
24
25 // EXTERNAL INCLUDES
26 #include <typeinfo>   // operator typeid
27
28
29 // INTERNAL INCLUDES
30 #include <dali/public-api/common/dali-common.h>
31
32 namespace Dali DALI_IMPORT_API
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   Any();
55
56   /**
57    * Destructor. Free resources.
58    */
59   ~Any();
60
61 /**
62    * @brief Pass Assert message
63    *
64    * @param assertMessage Assert message to report
65    */
66   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   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 )
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   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 Returns whether container holds a value
202    *
203    * @return true if the container is empty, else false.
204    */
205   bool Empty()
206   {
207     return ( NULL == mContainer ) ? true : false;
208   }
209
210   struct AnyContainerBase;    // Forward declaration for typedef
211   typedef AnyContainerBase* (*CloneFunc)( const AnyContainerBase& base );
212   typedef void (*DeleteFunc)( const AnyContainerBase* base );
213
214   /**
215    * Base container to hold type for match verification and instance cloning function
216    *
217    */
218   struct AnyContainerBase
219   {
220     /**
221      * @brief Constructor of base container
222      *
223      * @param type typeid of container
224      * @param cloneFunc Cloning function to replicate this container type
225      * @param deleteFunc Deleting function to destroy this container type
226      */
227     AnyContainerBase( const std::type_info& type, CloneFunc cloneFunc, DeleteFunc deleteFunc )
228     : mType( type ),
229       mCloneFunc( cloneFunc ),
230       mDeleteFunc( deleteFunc )
231     {}
232
233     /**
234      * @brief Get the typeid of this container
235      *
236      * @return type
237      */
238     const std::type_info& GetType() const
239     {
240       return mType;
241     }
242
243     const::std::type_info& mType;       // typeID
244     CloneFunc mCloneFunc;               // cloning function for this container
245     DeleteFunc mDeleteFunc;             // deleting function for this container
246   };
247
248
249   /**
250    * @brief Templated Clone function from container base
251    *
252    * @param base reference to container
253    */
254   template<typename Type>
255   struct AnyContainerImplCloner
256   {
257     static AnyContainerBase* Clone( const AnyContainerBase& base )
258     {
259       return new AnyContainerImpl< Type >( static_cast< AnyContainerImpl< Type > >( base ) );
260     }
261   };
262
263   /**
264    * @brief Templated Delete function from container base
265    *
266    * @param base pointer to container
267    */
268   template<typename Type>
269   struct AnyContainerImplDelete
270   {
271     static void Delete( const AnyContainerBase* base )
272     {
273       delete ( static_cast< const AnyContainerImpl< Type >* > ( base ) );
274     }
275   };
276
277   /**
278    * @brief Templated class to hold value for type
279    *
280    */
281   template<typename Type>
282   class AnyContainerImpl : public AnyContainerBase
283   {
284   public:
285
286     /**
287      * @brief Constructor to create container holding value of type Type
288      *
289      * @param value Value of Type
290      */
291     AnyContainerImpl( const Type& value )
292     : AnyContainerBase( typeid( Type ),
293                         static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
294                         static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) ),
295                         mValue( value )
296     {}
297
298     /**
299      * @brief Constructor to create new container of type from and existing container (cloning)
300      *
301      * @param base reference to base container to copy from
302      */
303     AnyContainerImpl( const AnyContainerBase& base )
304     : AnyContainerBase( typeid( Type ),
305                         static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
306                         static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) )
307     {
308       mValue = static_cast< const AnyContainerImpl& >( base ).GetValue();
309     }
310
311     /**
312      * @brief Get the container's stored value
313      *
314      * @return value of type Type
315      */
316     const Type& GetValue() const
317     {
318       return mValue;
319     }
320
321     /**
322      * @brief Set the container's stored value
323      *
324      * @param value of type Type
325      */
326     void SetValue( const Type& value )
327     {
328       mValue = value;
329     }
330
331     /**
332      * @brief Get a pointer to the value held
333      *
334      * @return pointer to the value of type Type
335      */
336     Type* GetPointerToValue()
337     {
338       return static_cast< Type* >( &mValue );
339     }
340
341     private:
342       Type mValue;
343   };
344
345   AnyContainerBase* mContainer;
346
347 };
348
349 /**
350  * AnyCast helper functions ( replicates boost functionality, but without exception generation )
351  */
352
353 /**
354  * @brief Extract a pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
355  *
356  * @param any Pointer to an Any object
357  *
358  * @return Pointer to the Type held
359  */
360 template<typename Type>inline Type* AnyCast( Any* any )
361 {
362   return any->GetPointer<Type>();
363 }
364
365 /**
366  * @brief Extract a const pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
367  *
368  * @param any const Pointer to an Any object
369  *
370  * @return const Pointer to the Type held
371  */
372 template<typename Type>inline const Type* AnyCast( const Any* any )
373 {
374   return any->GetPointer<Type>();
375 }
376
377 /**
378  * @brief Extract a held value of type Type from an Any object from a reference to that Any object
379  *
380  * @param any reference to an Any object
381  *
382  * @return Type value of type Type
383  */
384 template<typename Type>inline Type AnyCast( Any& any )
385 {
386   return any.Get<Type>();
387 }
388
389 /**
390  * @brief Extract a held value of type Type from an Any object from a const reference to that Any object
391  *
392  * @param any reference to an Any object
393  *
394  * @return Type value of type Type
395  */
396 template<typename Type>inline Type AnyCast( const Any& any )
397 {
398   return any.Get<Type>();
399 }
400
401 } // namespace Dali
402
403 /**
404  * @}
405  */
406 #endif // __DALI_ANY_TYPE_H__