[dali_2.3.26] Merge branch 'devel/master'
[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) 2022 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 Move Constructor.
105    * @SINCE_2_1.44
106    * @param[in] any Any to be moved
107    */
108   Any(Any&& any) noexcept
109   {
110     mContainer = any.mContainer;
111
112     // Remove input value's container.
113     any.mContainer = nullptr;
114   }
115
116   /**
117    * @brief Assigns a given value to the Any type.
118    *
119    * @SINCE_1_0.0
120    * @param[in] value The given value
121    * @return A reference to this
122    * @note If the types are different, then the current container will be re-created.
123    */
124   template<typename Type>
125   Any& operator=(const Type& value)
126   {
127     // If the container is empty then assign the new value
128     if(nullptr == mContainer)
129     {
130       mContainer = new AnyContainerImpl<Type>(value);
131     }
132     else
133     {
134       // Check to see if this type is compatible with current container?
135       if(mContainer->GetType() == typeid(Type))
136       {
137         // Same type so just set the new value
138         static_cast<AnyContainerImpl<Type>*>(mContainer)->SetValue(value);
139       }
140       else
141       {
142         // Incompatible types, so delete old container and assign a new one with this type and value
143         mContainer->mDeleteFunc(mContainer);
144         mContainer = new AnyContainerImpl<Type>(value);
145       }
146     }
147     return *this;
148   }
149
150   /**
151    * @brief Assignment operator.
152    *
153    * @SINCE_1_0.0
154    * @param[in] any Any to be assigned which contains a value of identical type to current contents.
155    * @return A reference to this
156    * @exception DaliException If parameter any is of a different type.
157    */
158   DALI_CORE_API Any& operator=(const Any& any);
159
160   /**
161    * @brief Move assignment operator.
162    *
163    * @SINCE_2_1.44
164    * @param[in] any Any to be moved which contains a value of identical type to current contents.
165    * @return A reference to this
166    */
167   DALI_CORE_API Any& operator=(Any&& any) noexcept;
168
169   /**
170    * @brief Gets a value of type Type from container.
171    *
172    * @SINCE_1_0.0
173    * @param[in] type destination of type Type to write to
174    */
175   template<typename Type>
176   void Get(Type& type) const
177   {
178     type = Get<Type>();
179   }
180
181   /**
182    * @brief Returns the type info of the stored value.
183    *
184    * @SINCE_1_0.0
185    * @return The std::type_info of the stored value or the type info of the void
186    * type if there is no value stored
187    */
188   DALI_CORE_API const std::type_info& GetType() const;
189
190   /**
191    * @brief Retrieves the stored value in the Any type.
192    *
193    * @SINCE_1_0.0
194    * @return The stored value
195    */
196   template<typename Type>
197   const Type& Get() const
198   {
199     if(nullptr == mContainer)
200     {
201       AssertAlways("Any::Get(). mContainer is NULL");
202     }
203     else if(mContainer->GetType() != typeid(Type)) // Check if the value has the same value than the Any type.
204     {
205       AssertAlways("Any::Get(). Trying to retrieve a value of a different type than the template one.");
206     }
207     return static_cast<AnyContainerImpl<Type>*>(mContainer)->GetValue();
208   }
209
210   /**
211    * @brief Returns pointer of Type to the value stored.
212    *
213    * @SINCE_1_0.0
214    * @return pointer to the value, or NULL if no value is contained
215    */
216   template<typename Type>
217   Type* GetPointer()
218   {
219     if(nullptr == mContainer)
220     {
221       return NULL;
222     }
223     // Check if the value has the same value than the Any type.
224     if(mContainer->GetType() != typeid(Type))
225     {
226       AssertAlways("Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one.");
227     }
228     return static_cast<AnyContainerImpl<Type>*>(mContainer)->GetPointerToValue();
229   }
230
231   /**
232    * @brief Returns pointer of Type to the value stored.
233    *
234    * @SINCE_1_0.0
235    * @return pointer to the value, or NULL if no value is contained
236    */
237   template<typename Type>
238   const Type* GetPointer() const
239   {
240     if(nullptr == mContainer)
241     {
242       return NULL;
243     }
244     // Check if the value has the same value than the Any type.
245     if(mContainer->GetType() != typeid(Type))
246     {
247       AssertAlways("Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one.");
248     }
249     return static_cast<AnyContainerImpl<Type>*>(mContainer)->GetPointerToValue();
250   }
251
252   /**
253    * @brief Returns whether container holds a value.
254    *
255    * @SINCE_1_0.0
256    * @return @c true if the container is empty, else @c false
257    */
258   bool Empty() const
259   {
260     return (nullptr == mContainer) ? true : false;
261   }
262
263   struct AnyContainerBase; // Forward declaration for typedef
264   using CloneFunc = AnyContainerBase* (*)(const AnyContainerBase&);
265
266   using DeleteFunc = void (*)(const AnyContainerBase*);
267
268   /**
269    * @brief Base container to hold type for match verification and instance cloning function.
270    *
271    * @SINCE_1_0.0
272    */
273   struct AnyContainerBase
274   {
275     /**
276      * @brief Constructor of base container.
277      *
278      * @SINCE_1_0.0
279      * @param[in] type typeid of container
280      * @param[in] cloneFunc Cloning function to replicate this container type
281      * @param[in] deleteFunc Deleting function to destroy this container type
282      */
283     AnyContainerBase(const std::type_info& type, CloneFunc cloneFunc, DeleteFunc deleteFunc)
284     : mType(type),
285       mCloneFunc(cloneFunc),
286       mDeleteFunc(deleteFunc)
287     {
288     }
289
290     /**
291      * @brief Gets the typeid of this container.
292      *
293      * @SINCE_1_0.0
294      * @return Type
295      */
296     const std::type_info& GetType() const
297     {
298       return mType;
299     }
300
301     const ::std::type_info& mType;       // typeID
302     CloneFunc               mCloneFunc;  // cloning function for this container
303     DeleteFunc              mDeleteFunc; // deleting function for this container
304   };
305
306   /**
307    * @brief Templated Clone function from container base.
308    *
309    * @SINCE_1_0.0
310    * @param[in] base The reference to container
311    */
312   template<typename Type>
313   struct AnyContainerImplCloner
314   {
315     static AnyContainerBase* Clone(const AnyContainerBase& base)
316     {
317       return new AnyContainerImpl<Type>(static_cast<AnyContainerImpl<Type> >(base));
318     }
319   };
320
321   /**
322    * @brief Templated Delete function from container base.
323    *
324    * @SINCE_1_0.0
325    * @param[in] base The pointer to container
326    */
327   template<typename Type>
328   struct AnyContainerImplDelete
329   {
330     static void Delete(const AnyContainerBase* base)
331     {
332       delete(static_cast<const AnyContainerImpl<Type>*>(base));
333     }
334   };
335
336   /**
337    * @brief Templated class to hold value for type.
338    *
339    * @SINCE_1_0.0
340    */
341   template<typename Type>
342   class AnyContainerImpl : public AnyContainerBase
343   {
344   public:
345     /**
346      * @brief Constructor to create container holding value of type Type.
347      *
348      * @SINCE_1_0.0
349      * @param[in] value Value of Type
350      */
351     AnyContainerImpl(const Type& value)
352     : AnyContainerBase(typeid(Type),
353                        static_cast<CloneFunc>(&AnyContainerImplCloner<Type>::Clone),
354                        static_cast<DeleteFunc>(&AnyContainerImplDelete<Type>::Delete)),
355       mValue(value)
356     {
357     }
358
359     /**
360      * @brief Constructor to create new container of type from and existing container (cloning).
361      *
362      * @SINCE_1_0.0
363      * @param[in] base The reference to base container to copy from
364      */
365     AnyContainerImpl(const AnyContainerBase& base)
366     : AnyContainerBase(typeid(Type),
367                        static_cast<CloneFunc>(&AnyContainerImplCloner<Type>::Clone),
368                        static_cast<DeleteFunc>(&AnyContainerImplDelete<Type>::Delete))
369     {
370       mValue = static_cast<const AnyContainerImpl&>(base).GetValue();
371     }
372
373     /**
374      * @brief Gets the container's stored value.
375      *
376      * @SINCE_1_0.0
377      * @return Value of type Type
378      */
379     const Type& GetValue() const
380     {
381       return mValue;
382     }
383
384     /**
385      * @brief Sets the container's stored value.
386      *
387      * @SINCE_1_0.0
388      * @param[in] value Value of type Type
389      */
390     void SetValue(const Type& value)
391     {
392       mValue = value;
393     }
394
395     /**
396      * @brief Gets a pointer to the value held.
397      *
398      * @SINCE_1_0.0
399      * @return Pointer to the value of type Type
400      */
401     Type* GetPointerToValue()
402     {
403       return static_cast<Type*>(&mValue);
404     }
405
406     /**
407      * @brief Gets a pointer to the value held.
408      *
409      * @SINCE_1_0.0
410      * @return Pointer to the value of type Type
411      */
412     const Type* GetPointerToValue() const
413     {
414       return static_cast<const Type*>(&mValue);
415     }
416
417   private:
418     Type mValue;
419   };
420
421 private:
422   AnyContainerBase* mContainer;
423 };
424
425 /**
426  * AnyCast helper functions
427  */
428
429 /**
430  * @brief Extracts a pointer to the held type of an Any object from a pointer to that Any object (NULL if empty).
431  *
432  * @SINCE_1_0.0
433  * @param[in] any Pointer to an Any object
434  *
435  * @return Pointer to the Type held
436  */
437 template<typename Type>
438 inline Type* AnyCast(Any* any)
439 {
440   return any->GetPointer<Type>();
441 }
442
443 /**
444  * @brief Extracts a const pointer to the held type of an Any object from a pointer to that Any object (NULL if empty).
445  *
446  * @SINCE_1_0.0
447  * @param[in] any const Pointer to an Any object
448  *
449  * @return const Pointer to the Type held
450  */
451 template<typename Type>
452 inline const Type* AnyCast(const Any* any)
453 {
454   return any->GetPointer<Type>();
455 }
456
457 /**
458  * @brief Extracts a held value of type Type from an Any object from a reference to that Any object.
459  *
460  * @SINCE_1_0.0
461  * @param[in] any The reference to an Any object
462  *
463  * @return Type value of type Type
464  */
465 template<typename Type>
466 inline Type AnyCast(Any& any)
467 {
468   return any.Get<Type>();
469 }
470
471 /**
472  * @brief Extracts a held value of type Type from an Any object from a const reference to that Any object.
473  *
474  * @SINCE_1_0.0
475  * @param[in] any The reference to an Any object
476  *
477  * @return Type value of type Type
478  */
479 template<typename Type>
480 inline Type AnyCast(const Any& any)
481 {
482   return any.Get<Type>();
483 }
484
485 /**
486  * @brief Extracts a reference to the held value of type Type from an Any object from a reference to that Any object
487  *
488  * @SINCE_1_0.0
489  * @param[in] any The reference to an Any object
490  *
491  * @return A reference to the Type value of type Type
492  */
493 template<typename Type>
494 inline Type& AnyCastReference(Any& any)
495 {
496   return any.Get<Type>();
497 }
498
499 /**
500  * @brief Extracts a const reference to the held value of type Type from an Any object from a const reference to that Any object.
501  *
502  * @SINCE_1_0.0
503  * @param[in] any The reference to an Any object
504  *
505  * @return A const reference to the Type value of type Type
506  */
507 template<typename Type>
508 inline const Type& AnyCastReference(const Any& any)
509 {
510   return any.Get<Type>();
511 }
512
513 /**
514  * @}
515  */
516 } // namespace Dali
517
518 #endif // DALI_ANY_TYPE_H