1 #ifndef DALI_ANY_TYPE_H
2 #define DALI_ANY_TYPE_H
5 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <cstddef> // NULL
23 #include <typeinfo> // operator typeid
26 #include <dali/public-api/common/dali-common.h>
31 * @addtogroup dali_core_object
36 * @brief Stores a value of any type.
40 * Any uintVariable = 5u;
41 * Any floatVariable( 4.5f );
42 * Any strVariable( std::string( "Hello world" ) );
44 * uint32_t variable = AnyCast< uint32_t >( uintVariable );
45 * if ( typeid( int ) == uintVariable.GetType() )
53 * @brief Default constructor.
59 * @brief Destructor. Free resources.
65 * @brief Passes Assert message.
68 * @param[in] assertMessage Assert message to report
70 DALI_CORE_API static void AssertAlways(const char* assertMessage);
73 * @brief Constructs a Any type with the given value.
76 * @param[in] value The given value
78 template<typename Type>
79 Any(const Type& value)
80 : mContainer(new AnyContainerImpl<Type>(value))
85 * @brief Copy Constructor.
87 * @param[in] any Any to be copied
91 // If container isn't empty then copy the container?
92 if(nullptr != any.mContainer)
94 mContainer = any.mContainer->mCloneFunc(*any.mContainer);
98 // Otherwise mark new container as empty
104 * @brief Move Constructor.
106 * @param[in] any Any to be moved
108 Any(Any&& any) noexcept
110 mContainer = any.mContainer;
112 // Remove input value's container.
113 any.mContainer = nullptr;
117 * @brief Assigns a given value to the Any type.
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.
124 template<typename Type>
125 Any& operator=(const Type& value)
127 // If the container is empty then assign the new value
128 if(nullptr == mContainer)
130 mContainer = new AnyContainerImpl<Type>(value);
134 // Check to see if this type is compatible with current container?
135 if(mContainer->GetType() == typeid(Type))
137 // Same type so just set the new value
138 static_cast<AnyContainerImpl<Type>*>(mContainer)->SetValue(value);
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);
151 * @brief Assignment operator.
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.
158 DALI_CORE_API Any& operator=(const Any& any);
161 * @brief Move assignment operator.
164 * @param[in] any Any to be moved which contains a value of identical type to current contents.
165 * @return A reference to this
167 DALI_CORE_API Any& operator=(Any&& any) noexcept;
170 * @brief Gets a value of type Type from container.
173 * @param[in] type destination of type Type to write to
175 template<typename Type>
176 void Get(Type& type) const
182 * @brief Returns the type info of the stored value.
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
188 DALI_CORE_API const std::type_info& GetType() const;
191 * @brief Retrieves the stored value in the Any type.
194 * @return The stored value
196 template<typename Type>
197 const Type& Get() const
199 if(nullptr == mContainer)
201 AssertAlways("Any::Get(). mContainer is NULL");
203 else if(mContainer->GetType() != typeid(Type)) // Check if the value has the same value than the Any type.
205 AssertAlways("Any::Get(). Trying to retrieve a value of a different type than the template one.");
207 return static_cast<AnyContainerImpl<Type>*>(mContainer)->GetValue();
211 * @brief Returns pointer of Type to the value stored.
214 * @return pointer to the value, or NULL if no value is contained
216 template<typename Type>
219 if(nullptr == mContainer)
223 // Check if the value has the same value than the Any type.
224 if(mContainer->GetType() != typeid(Type))
226 AssertAlways("Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one.");
228 return static_cast<AnyContainerImpl<Type>*>(mContainer)->GetPointerToValue();
232 * @brief Returns pointer of Type to the value stored.
235 * @return pointer to the value, or NULL if no value is contained
237 template<typename Type>
238 const Type* GetPointer() const
240 if(nullptr == mContainer)
244 // Check if the value has the same value than the Any type.
245 if(mContainer->GetType() != typeid(Type))
247 AssertAlways("Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one.");
249 return static_cast<AnyContainerImpl<Type>*>(mContainer)->GetPointerToValue();
253 * @brief Returns whether container holds a value.
256 * @return @c true if the container is empty, else @c false
260 return (nullptr == mContainer) ? true : false;
263 struct AnyContainerBase; // Forward declaration for typedef
264 using CloneFunc = AnyContainerBase* (*)(const AnyContainerBase&);
266 using DeleteFunc = void (*)(const AnyContainerBase*);
269 * @brief Base container to hold type for match verification and instance cloning function.
273 struct AnyContainerBase
276 * @brief Constructor of base container.
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
283 AnyContainerBase(const std::type_info& type, CloneFunc cloneFunc, DeleteFunc deleteFunc)
285 mCloneFunc(cloneFunc),
286 mDeleteFunc(deleteFunc)
291 * @brief Gets the typeid of this container.
296 const std::type_info& GetType() const
301 const ::std::type_info& mType; // typeID
302 CloneFunc mCloneFunc; // cloning function for this container
303 DeleteFunc mDeleteFunc; // deleting function for this container
307 * @brief Templated Clone function from container base.
310 * @param[in] base The reference to container
312 template<typename Type>
313 struct AnyContainerImplCloner
315 static AnyContainerBase* Clone(const AnyContainerBase& base)
317 return new AnyContainerImpl<Type>(static_cast<AnyContainerImpl<Type> >(base));
322 * @brief Templated Delete function from container base.
325 * @param[in] base The pointer to container
327 template<typename Type>
328 struct AnyContainerImplDelete
330 static void Delete(const AnyContainerBase* base)
332 delete(static_cast<const AnyContainerImpl<Type>*>(base));
337 * @brief Templated class to hold value for type.
341 template<typename Type>
342 class AnyContainerImpl : public AnyContainerBase
346 * @brief Constructor to create container holding value of type Type.
349 * @param[in] value Value of Type
351 AnyContainerImpl(const Type& value)
352 : AnyContainerBase(typeid(Type),
353 static_cast<CloneFunc>(&AnyContainerImplCloner<Type>::Clone),
354 static_cast<DeleteFunc>(&AnyContainerImplDelete<Type>::Delete)),
360 * @brief Constructor to create new container of type from and existing container (cloning).
363 * @param[in] base The reference to base container to copy from
365 AnyContainerImpl(const AnyContainerBase& base)
366 : AnyContainerBase(typeid(Type),
367 static_cast<CloneFunc>(&AnyContainerImplCloner<Type>::Clone),
368 static_cast<DeleteFunc>(&AnyContainerImplDelete<Type>::Delete))
370 mValue = static_cast<const AnyContainerImpl&>(base).GetValue();
374 * @brief Gets the container's stored value.
377 * @return Value of type Type
379 const Type& GetValue() const
385 * @brief Sets the container's stored value.
388 * @param[in] value Value of type Type
390 void SetValue(const Type& value)
396 * @brief Gets a pointer to the value held.
399 * @return Pointer to the value of type Type
401 Type* GetPointerToValue()
403 return static_cast<Type*>(&mValue);
407 * @brief Gets a pointer to the value held.
410 * @return Pointer to the value of type Type
412 const Type* GetPointerToValue() const
414 return static_cast<const Type*>(&mValue);
422 AnyContainerBase* mContainer;
426 * AnyCast helper functions
430 * @brief Extracts a pointer to the held type of an Any object from a pointer to that Any object (NULL if empty).
433 * @param[in] any Pointer to an Any object
435 * @return Pointer to the Type held
437 template<typename Type>
438 inline Type* AnyCast(Any* any)
440 return any->GetPointer<Type>();
444 * @brief Extracts a const pointer to the held type of an Any object from a pointer to that Any object (NULL if empty).
447 * @param[in] any const Pointer to an Any object
449 * @return const Pointer to the Type held
451 template<typename Type>
452 inline const Type* AnyCast(const Any* any)
454 return any->GetPointer<Type>();
458 * @brief Extracts a held value of type Type from an Any object from a reference to that Any object.
461 * @param[in] any The reference to an Any object
463 * @return Type value of type Type
465 template<typename Type>
466 inline Type AnyCast(Any& any)
468 return any.Get<Type>();
472 * @brief Extracts a held value of type Type from an Any object from a const reference to that Any object.
475 * @param[in] any The reference to an Any object
477 * @return Type value of type Type
479 template<typename Type>
480 inline Type AnyCast(const Any& any)
482 return any.Get<Type>();
486 * @brief Extracts a reference to the held value of type Type from an Any object from a reference to that Any object
489 * @param[in] any The reference to an Any object
491 * @return A reference to the Type value of type Type
493 template<typename Type>
494 inline Type& AnyCastReference(Any& any)
496 return any.Get<Type>();
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.
503 * @param[in] any The reference to an Any object
505 * @return A const reference to the Type value of type Type
507 template<typename Type>
508 inline const Type& AnyCastReference(const Any& any)
510 return any.Get<Type>();
518 #endif // DALI_ANY_TYPE_H