Plasma Engine  2.0
Loading...
Searching...
No Matches
Variant.h
1#pragma once
2
3#include <Foundation/Algorithm/HashingUtils.h>
4#include <Foundation/Containers/DynamicArray.h>
5#include <Foundation/Containers/HashTable.h>
6#include <Foundation/Math/Declarations.h>
7#include <Foundation/Strings/HashedString.h>
8#include <Foundation/Threading/AtomicInteger.h>
9#include <Foundation/Types/TypedPointer.h>
10#include <Foundation/Types/Types.h>
11#include <Foundation/Types/VariantType.h>
12
13#include <Foundation/Reflection/Implementation/DynamicRTTI.h>
14#include <Foundation/Utilities/ConversionUtils.h>
15
16class plRTTI;
17
24{
25 PL_DECLARE_POD_TYPE();
26 const void* m_pObject = nullptr;
27 const plRTTI* m_pType = nullptr;
28
29 bool operator==(const plTypedObject& rhs) const
30 {
31 return m_pObject == rhs.m_pObject;
32 }
33 PL_ADD_DEFAULT_OPERATOR_NOTEQUAL(const plTypedObject&);
34};
35
43class PL_FOUNDATION_DLL plVariant
44{
45public:
46 using Type = plVariantType;
47 template <typename T>
49
52 {
53 PL_ALWAYS_INLINE StringWrapper(const char* szStr)
54 : m_str(szStr)
55 {
56 }
57 const char* m_str;
58 };
59
61 plVariant(); // [tested]
62
68 plVariant(const plVariant& other); // [tested]
69
71 plVariant(plVariant&& other) noexcept; // [tested]
72
73 plVariant(const bool& value);
74 plVariant(const plInt8& value);
75 plVariant(const plUInt8& value);
76 plVariant(const plInt16& value);
77 plVariant(const plUInt16& value);
78 plVariant(const plInt32& value);
79 plVariant(const plUInt32& value);
80 plVariant(const plInt64& value);
81 plVariant(const plUInt64& value);
82 plVariant(const float& value);
83 plVariant(const double& value);
84 plVariant(const plColor& value);
85 plVariant(const plVec2& value);
86 plVariant(const plVec3& value);
87 plVariant(const plVec4& value);
88 plVariant(const plVec2I32& value);
89 plVariant(const plVec3I32& value);
90 plVariant(const plVec4I32& value);
91 plVariant(const plVec2U32& value);
92 plVariant(const plVec3U32& value);
93 plVariant(const plVec4U32& value);
94 plVariant(const plQuat& value);
95 plVariant(const plMat3& value);
96 plVariant(const plMat4& value);
97 plVariant(const plTransform& value);
98 plVariant(const char* value);
99 plVariant(const plString& value);
100 plVariant(const plUntrackedString& value);
101 plVariant(const plStringView& value, bool bCopyString = true);
102 plVariant(const plDataBuffer& value);
103 plVariant(const plTime& value);
104 plVariant(const plUuid& value);
105 plVariant(const plAngle& value);
106 plVariant(const plColorGammaUB& value);
107 plVariant(const plHashedString& value);
108 plVariant(const plTempHashedString& value);
109
110 plVariant(const plVariantArray& value);
111 plVariant(const plVariantDictionary& value);
112
113 plVariant(const plTypedPointer& value);
114 plVariant(const plTypedObject& value);
115
116 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::CustomTypeCast, int> = 0>
117 plVariant(const T& value);
118
119 template <typename T>
120 plVariant(const T* value);
121
123 plVariant(void* value, const plRTTI* pType);
124
126 void CopyTypedObject(const void* value, const plRTTI* pType); // [tested]
127
129 void MoveTypedObject(void* value, const plRTTI* pType); // [tested]
130
132 ~plVariant();
133
135 void operator=(const plVariant& other); // [tested]
136
138 void operator=(plVariant&& other) noexcept; // [tested]
139
143 template <typename T>
144 void operator=(const T& value); // [tested]
145
152 bool operator==(const plVariant& other) const; // [tested]
153
154 PL_ADD_DEFAULT_OPERATOR_NOTEQUAL(const plVariant&);
155
157 template <typename T>
158 bool operator==(const T& other) const; // [tested]
159
160#if PL_DISABLED(PL_USE_CPP20_OPERATORS)
162 template <typename T>
163 bool operator!=(const T& other) const // [tested]
164 {
165 return !(*this == other);
166 }
167#endif
168
170 bool IsValid() const; // [tested]
171
175 bool IsNumber() const; // [tested]
176
178 bool IsFloatingPoint() const; // [tested]
179
181 bool IsString() const; // [tested]
182
184 bool IsHashedString() const;
185
190 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::DirectCast, int> = 0>
191 bool IsA() const; // [tested]
192
193 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::PointerCast, int> = 0>
194 bool IsA() const; // [tested]
195
196 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::TypedObject, int> = 0>
197 bool IsA() const; // [tested]
198
199 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::CustomTypeCast, int> = 0>
200 bool IsA() const; // [tested]
201
203 Type::Enum GetType() const; // [tested]
204
212 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::DirectCast, int> = 0>
213 const T& Get() const; // [tested]
214
215 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::PointerCast, int> = 0>
216 T Get() const; // [tested]
217
218 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::TypedObject, int> = 0>
219 const T Get() const; // [tested]
220
221 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::CustomTypeCast, int> = 0>
222 const T& Get() const; // [tested]
223
226 plTypedPointer GetWriteAccess(); // [tested]
227
228 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::DirectCast, int> = 0>
229 T& GetWritable(); // [tested]
230
231 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::PointerCast, int> = 0>
232 T GetWritable(); // [tested]
233
234 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::CustomTypeCast, int> = 0>
235 T& GetWritable(); // [tested]
236
237
240 const void* GetData() const; // [tested]
241
244 const plRTTI* GetReflectedType() const; // [tested]
245
249 const plVariant operator[](plUInt32 uiIndex) const; // [tested]
250
254 const plVariant operator[](StringWrapper key) const; // [tested]
255
268 template <typename T>
269 bool CanConvertTo() const; // [tested]
270
272 bool CanConvertTo(Type::Enum type) const; // [tested]
273
280 template <typename T>
281 T ConvertTo(plResult* out_pConversionStatus = nullptr) const; // [tested]
282
284 plVariant ConvertTo(Type::Enum type, plResult* out_pConversionStatus = nullptr) const; // [tested]
285
293 template <typename Functor, class... Args>
294 static auto DispatchTo(Functor& ref_functor, Type::Enum type, Args&&... args); // [tested]
295
297 plUInt64 ComputeHash(plUInt64 uiSeed = 0) const;
298
299private:
300 friend class plVariantHelper;
301 friend struct CompareFunc;
302 friend struct GetTypeFromVariantFunc;
303
304 struct SharedData
305 {
306 void* m_Ptr;
307 const plRTTI* m_pType;
308 plAtomicInteger32 m_uiRef = 1;
309 PL_ALWAYS_INLINE SharedData(void* pPtr, const plRTTI* pType)
310 : m_Ptr(pPtr)
311 , m_pType(pType)
312 {
313 }
314 virtual ~SharedData() = default;
315 virtual SharedData* Clone() const = 0;
316 };
317
318 template <typename T>
319 class TypedSharedData : public SharedData
320 {
321 private:
322 T m_t;
323
324 public:
325 PL_ALWAYS_INLINE TypedSharedData(const T& value, const plRTTI* pType = nullptr)
326 : SharedData(&m_t, pType)
327 , m_t(value)
328 {
329 }
330
331 virtual SharedData* Clone() const override
332 {
333 return PL_DEFAULT_NEW(TypedSharedData<T>, m_t, m_pType);
334 }
335 };
336
337 class RTTISharedData : public SharedData
338 {
339 public:
340 RTTISharedData(void* pData, const plRTTI* pType);
341
342 ~RTTISharedData();
343
344 virtual SharedData* Clone() const override;
345 };
346
347 struct InlinedStruct
348 {
349 constexpr static int DataSize = 4 * sizeof(float) - sizeof(void*);
350 plUInt8 m_Data[DataSize];
351 const plRTTI* m_pType;
352 };
353
354 union Data
355 {
356 float f[4];
357 SharedData* shared;
358 InlinedStruct inlined;
359 } m_Data;
360
361 plUInt32 m_uiType : 31;
362 plUInt32 m_bIsShared : 1; // NOLINT(pl*)
363
364 template <typename T>
365 void InitInplace(const T& value);
366
367 template <typename T>
368 void InitShared(const T& value);
369
370 template <typename T>
371 void InitTypedObject(const T& value, plTraitInt<0>);
372 template <typename T>
373 void InitTypedObject(const T& value, plTraitInt<1>);
374
375 void InitTypedPointer(void* value, const plRTTI* pType);
376
377 void Release();
378 void CopyFrom(const plVariant& other);
379 void MoveFrom(plVariant&& other);
380
381 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::DirectCast, int> = 0>
382 const T& Cast() const;
383 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::PointerCast, int> = 0>
384 T Cast() const;
385 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::TypedObject, int> = 0>
386 const T Cast() const;
387 template <typename T, typename std::enable_if_t<plVariantTypeDeduction<T>::classification == plVariantClass::CustomTypeCast, int> = 0>
388 const T& Cast() const;
389
390 static bool IsNumberStatic(plUInt32 type);
391 static bool IsFloatingPointStatic(plUInt32 type);
392 static bool IsStringStatic(plUInt32 type);
393 static bool IsHashedStringStatic(plUInt32 type);
394 static bool IsVector2Static(plUInt32 type);
395 static bool IsVector3Static(plUInt32 type);
396 static bool IsVector4Static(plUInt32 type);
397
398 // Needed to prevent including plRTTI in plVariant.h
399 static bool IsDerivedFrom(const plRTTI* pType1, const plRTTI* pType2);
400 static plStringView GetTypeName(const plRTTI* pType);
401
402 template <typename T>
403 T ConvertNumber() const;
404};
405
410template <typename T>
411PL_ALWAYS_INLINE T plDynamicCast(const plVariant& variant)
412{
413 if (variant.IsA<T>())
414 {
415 return variant.Get<T>();
416 }
417
418 return nullptr;
419}
420
421// Simple math operator overloads. An invalid variant is returned if the given variants have incompatible types.
422PL_FOUNDATION_DLL plVariant operator+(const plVariant& a, const plVariant& b);
423PL_FOUNDATION_DLL plVariant operator-(const plVariant& a, const plVariant& b);
424PL_FOUNDATION_DLL plVariant operator*(const plVariant& a, const plVariant& b);
425PL_FOUNDATION_DLL plVariant operator/(const plVariant& a, const plVariant& b);
426
427namespace plMath
428{
432 PL_FOUNDATION_DLL plVariant Lerp(const plVariant& a, const plVariant& b, double fFactor);
433} // namespace plMath
434
435#include <Foundation/Types/Implementation/VariantHelper_inl.h>
436
437#include <Foundation/Types/Implementation/Variant_inl.h>
Float wrapper struct for a safe usage and conversions of angles.
Definition Angle.h:10
A 8bit per channel unsigned normalized (values interpreted as 0-1) color storage format that represen...
Definition Color8UNorm.h:99
plColor represents an RGBA color in linear color space. Values are stored as float,...
Definition Color.h:44
This class is optimized to take nearly no memory (sizeof(void*)) and to allow very fast checks whethe...
Definition HashedString.h:25
This class holds information about reflected types. Each instance represents one type that is known t...
Definition RTTI.h:30
plStringView represent a read-only sub-string of a larger string, as it can store a dedicated string ...
Definition StringView.h:34
A class to use together with plHashedString for quick comparisons with temporary strings that need no...
Definition HashedString.h:151
This data type is the abstraction for 128-bit Uuid (also known as GUID) instances.
Definition Uuid.h:11
Definition VariantHelper_inl.h:175
plVariant is a class that can store different types of variables, which is useful in situations where...
Definition Variant.h:44
bool operator==(const T &other) const
See non-templated operator==.
void operator=(const T &value)
Deduces the type of T and stores value.
bool CanConvertTo() const
Returns whether the stored type can generally be converted to the desired type.
const T & Get() const
Returns the variants value as the provided type.
bool IsA() const
Returns whether the stored type is exactly the given type.
This namespace provides common math-functionality as functions.
Definition Constants.h:6
PL_FORCE_INLINE T Lerp(T f1, T f2, float fFactor)
Returns the linear interpolation of f1 and f2. factor is a value between 0 and 1.
Definition Math_inl.h:230
Default enum for returning failure or success, instead of using a bool.
Definition Types.h:54
The time class encapsulates a double value storing the time in seconds.
Definition Time.h:12
Type traits.
Definition TypeTraits.h:12
Defines a reference to an immutable object owned by an plVariant.
Definition Variant.h:24
A typed raw pointer.
Definition TypedPointer.h:13
helper struct to wrap a string pointer
Definition Variant.h:52
@ CustomTypeCast
Custom object types.
Definition VariantType.h:90
@ PointerCast
Any cast to T*.
Definition VariantType.h:88
@ DirectCast
A standard type.
Definition VariantType.h:87
@ TypedObject
plTypedObject cast. Needed because at no point does and plVariant ever store a plTypedObject so it ca...
Definition VariantType.h:89
A helper struct to convert the C++ type, which is passed as the template argument,...
Definition VariantType.h:97
This enum describes the type of data that is currently stored inside the variant.
Definition VariantType.h:20
Enum
This enum describes the type of data that is currently stored inside the variant. Note that changes t...
Definition VariantType.h:26