Merge branch 'devel/master' 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) 2020 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 <cstddef>  // NULL
23 #include <typeinfo> // operator typeid
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(nullptr != any.mContainer)
93     {
94       mContainer = any.mContainer->mCloneFunc(*any.mContainer);
95     }
96     else
97     {
98       // Otherwise mark new container as empty
99       mContainer = nullptr;
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(nullptr == 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(nullptr == 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     }
187     return static_cast<AnyContainerImpl<Type>*>(mContainer)->GetValue();
188   }
189
190   /**
191    * @brief Returns pointer of Type to the value stored.
192    *
193    * @SINCE_1_0.0
194    * @return pointer to the value, or NULL if no value is contained
195    */
196   template<typename Type>
197   Type* GetPointer()
198   {
199     if(nullptr == mContainer)
200     {
201       return NULL;
202     }
203     // Check if the value has the same value than the Any type.
204     if(mContainer->GetType() != typeid(Type))
205     {
206       AssertAlways("Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one.");
207     }
208     return static_cast<AnyContainerImpl<Type>*>(mContainer)->GetPointerToValue();
209   }
210
211   /**
212    * @brief Returns pointer of Type to the value stored.
213    *
214    * @SINCE_1_0.0
215    * @return pointer to the value, or NULL if no value is contained
216    */
217   template<typename Type>
218   const Type* GetPointer() const
219   {
220     if(nullptr == mContainer)
221     {
222       return NULL;
223     }
224     // Check if the value has the same value than the Any type.
225     if(mContainer->GetType() != typeid(Type))
226     {
227       AssertAlways("Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one.");
228     }
229     return static_cast<AnyContainerImpl<Type>*>(mContainer)->GetPointerToValue();
230   }
231
232   /**
233    * @brief Returns whether container holds a value.
234    *
235    * @SINCE_1_0.0
236    * @return @c true if the container is empty, else @c false
237    */
238   bool Empty() const
239   {
240     return (nullptr == mContainer) ? true : false;
241   }
242
243   struct AnyContainerBase; // Forward declaration for typedef
244   using CloneFunc = AnyContainerBase* (*)(const AnyContainerBase&);
245
246   using DeleteFunc = void (*)(const AnyContainerBase*);
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     /**
271      * @brief Gets the typeid of this container.
272      *
273      * @SINCE_1_0.0
274      * @return Type
275      */
276     const std::type_info& GetType() const
277     {
278       return mType;
279     }
280
281     const ::std::type_info& mType;       // typeID
282     CloneFunc               mCloneFunc;  // cloning function for this container
283     DeleteFunc              mDeleteFunc; // deleting function for this container
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      * @brief Constructor to create container holding value of type Type.
327      *
328      * @SINCE_1_0.0
329      * @param[in] value Value of Type
330      */
331     AnyContainerImpl(const Type& value)
332     : AnyContainerBase(typeid(Type),
333                        static_cast<CloneFunc>(&AnyContainerImplCloner<Type>::Clone),
334                        static_cast<DeleteFunc>(&AnyContainerImplDelete<Type>::Delete)),
335       mValue(value)
336     {
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  * AnyCast helper functions
406  */
407
408 /**
409  * @brief Extracts a pointer to the held type of an Any object from a pointer to that Any object (NULL if empty).
410  *
411  * @SINCE_1_0.0
412  * @param[in] any Pointer to an Any object
413  *
414  * @return Pointer to the Type held
415  */
416 template<typename Type>
417 inline Type* AnyCast(Any* any)
418 {
419   return any->GetPointer<Type>();
420 }
421
422 /**
423  * @brief Extracts a const pointer to the held type of an Any object from a pointer to that Any object (NULL if empty).
424  *
425  * @SINCE_1_0.0
426  * @param[in] any const Pointer to an Any object
427  *
428  * @return const Pointer to the Type held
429  */
430 template<typename Type>
431 inline const Type* AnyCast(const Any* any)
432 {
433   return any->GetPointer<Type>();
434 }
435
436 /**
437  * @brief Extracts a held value of type Type from an Any object from a reference to that Any object.
438  *
439  * @SINCE_1_0.0
440  * @param[in] any The reference to an Any object
441  *
442  * @return Type value of type Type
443  */
444 template<typename Type>
445 inline Type AnyCast(Any& any)
446 {
447   return any.Get<Type>();
448 }
449
450 /**
451  * @brief Extracts a held value of type Type from an Any object from a const reference to that Any object.
452  *
453  * @SINCE_1_0.0
454  * @param[in] any The reference to an Any object
455  *
456  * @return Type value of type Type
457  */
458 template<typename Type>
459 inline Type AnyCast(const Any& any)
460 {
461   return any.Get<Type>();
462 }
463
464 /**
465  * @brief Extracts a reference to the held value of type Type from an Any object from a reference to that Any object
466  *
467  * @SINCE_1_0.0
468  * @param[in] any The reference to an Any object
469  *
470  * @return A reference to the Type value of type Type
471  */
472 template<typename Type>
473 inline Type& AnyCastReference(Any& any)
474 {
475   return any.Get<Type>();
476 }
477
478 /**
479  * @brief Extracts a const reference to the held value of type Type from an Any object from a const reference to that Any object.
480  *
481  * @SINCE_1_0.0
482  * @param[in] any The reference to an Any object
483  *
484  * @return A const reference to the Type value of type Type
485  */
486 template<typename Type>
487 inline const Type& AnyCastReference(const Any& any)
488 {
489   return any.Get<Type>();
490 }
491
492 /**
493  * @}
494  */
495 } // namespace Dali
496
497 #endif // DALI_ANY_TYPE_H