Plasma Engine  2.0
Loading...
Searching...
No Matches
PointerWithFlags.h
1#pragma once
2
3#include <Foundation/Basics.h>
4
10template <typename PtrType, plUInt8 NumFlagBits = 2>
12{
13private:
14 enum : size_t
15 {
16 AllOnes = (std::size_t)(-1),
17 PtrBits = sizeof(void*) * 8,
18 FlagsMask = (AllOnes >> (PtrBits - NumFlagBits)),
19 PtrMask = ~FlagsMask,
20 };
21
22 void* m_pPtr = nullptr;
23
24public:
26 plPointerWithFlags() = default;
27
29 explicit plPointerWithFlags(PtrType* pPtr, plUInt8 uiFlags = 0) { SetPtrAndFlags(pPtr, uiFlags); }
30
32 void SetPtrAndFlags(PtrType* pPtr, plUInt8 uiFlags)
33 {
34 const std::uintptr_t isrc = *reinterpret_cast<std::uintptr_t*>(&pPtr);
35 std::uintptr_t& iptr = *reinterpret_cast<std::uintptr_t*>(&m_pPtr);
36
37 iptr = (isrc & PtrMask) | (uiFlags & FlagsMask);
38 }
39
41 const PtrType* GetPtr() const
42 {
43 const std::uintptr_t& iptr = *reinterpret_cast<const std::uintptr_t*>(&m_pPtr);
44 return reinterpret_cast<const PtrType*>(iptr & PtrMask); // mask off lower N bits
45 }
46
48 PtrType* GetPtr()
49 {
50 std::uintptr_t& iptr = *reinterpret_cast<std::uintptr_t*>(&m_pPtr);
51 return reinterpret_cast<PtrType*>(iptr & PtrMask); // mask off lower N bits
52 }
53
55 void SetPtr(PtrType* pPtr)
56 {
57 const std::uintptr_t isrc = *reinterpret_cast<std::uintptr_t*>(&pPtr);
58 PL_ASSERT_DEBUG(
59 (isrc & FlagsMask) == 0, "The given pointer does not have an {} byte alignment and thus cannot be stored lossless.", 1u << NumFlagBits);
60
61 std::uintptr_t& iptr = *reinterpret_cast<std::uintptr_t*>(&m_pPtr);
62
63 iptr = (isrc & PtrMask) | (iptr & FlagsMask);
64 }
66 plUInt8 GetFlags() const
67 {
68 const std::uintptr_t& iptr = *reinterpret_cast<const std::uintptr_t*>(&m_pPtr);
69 return static_cast<plUInt8>(iptr & FlagsMask);
70 }
71
73 void SetFlags(plUInt8 uiFlags)
74 {
75 PL_ASSERT_DEBUG(uiFlags <= FlagsMask, "The flag value {} requires more than {} bits", uiFlags, NumFlagBits);
76
77 std::uintptr_t& iptr = *reinterpret_cast<std::uintptr_t*>(&m_pPtr);
78
79 iptr = (iptr & PtrMask) | (uiFlags & FlagsMask);
80 }
81
83 operator PtrType*() { return GetPtr(); }
84
86 operator const PtrType*() const { return GetPtr(); }
87
89 void operator=(PtrType* pPtr) { SetPtr(pPtr); }
90
92 template <typename = typename std::enable_if<std::is_const<PtrType>::value == false>>
93 bool operator==(const PtrType* pPtr) const
94 {
95 return GetPtr() == pPtr;
96 }
97
98#if PL_DISABLED(PL_USE_CPP20_OPERATORS)
100 template <typename = typename std::enable_if<std::is_const<PtrType>::value == false>>
101 bool operator!=(const PtrType* pPtr) const
102 {
103 return !(*this == pPtr);
104 }
105#endif
106
108 {
109 return GetPtr() == rhs.GetPtr();
110 }
111
112 PL_ADD_DEFAULT_OPERATOR_NOTEQUAL(const plPointerWithFlags<PtrType, NumFlagBits>&);
113
115 bool operator==(PtrType* pPtr) const { return GetPtr() == pPtr; }
116 PL_ADD_DEFAULT_OPERATOR_NOTEQUAL(PtrType*);
117
119 bool operator==(std::nullptr_t) const { return GetPtr() == nullptr; }
120 PL_ADD_DEFAULT_OPERATOR_NOTEQUAL(std::nullptr_t);
121
123 explicit operator bool() const { return GetPtr() != nullptr; }
124
126 const PtrType* operator->() const { return GetPtr(); }
127
129 PtrType* operator->() { return GetPtr(); }
130
132 const PtrType& operator*() const { return *GetPtr(); }
133
135 PtrType& operator*() { return *GetPtr(); }
136};
A wrapper around a raw pointer that allows to use the lower N bits for flags.
Definition PointerWithFlags.h:12
const PtrType & operator*() const
Dereferences the pointer.
Definition PointerWithFlags.h:132
void SetPtrAndFlags(PtrType *pPtr, plUInt8 uiFlags)
Changes the pointer and flags.
Definition PointerWithFlags.h:32
const PtrType * GetPtr() const
Returns the masked off pointer value.
Definition PointerWithFlags.h:41
PtrType * GetPtr()
Returns the masked off pointer value.
Definition PointerWithFlags.h:48
plPointerWithFlags(PtrType *pPtr, plUInt8 uiFlags=0)
Initializes the pointer and flags.
Definition PointerWithFlags.h:29
void SetPtr(PtrType *pPtr)
Changes the pointer value only. Flags stay unchanged.
Definition PointerWithFlags.h:55
bool operator==(PtrType *pPtr) const
Compares the pointer part for equality (flags are ignored)
Definition PointerWithFlags.h:115
plUInt8 GetFlags() const
Returns the flags value only.
Definition PointerWithFlags.h:66
bool operator==(const PtrType *pPtr) const
Compares the pointer part for equality (flags are ignored)
Definition PointerWithFlags.h:93
plPointerWithFlags()=default
Initializes the pointer and flags with zero.
void SetFlags(plUInt8 uiFlags)
Changes only the flags value. The given value must fit into the reserved bits.
Definition PointerWithFlags.h:73
bool operator==(std::nullptr_t) const
Compares the pointer part for equality (flags are ignored)
Definition PointerWithFlags.h:119
void operator=(PtrType *pPtr)
Changes the pointer value only. Flags stay unchanged.
Definition PointerWithFlags.h:89
PtrType * operator->()
Dereferences the pointer.
Definition PointerWithFlags.h:129
PtrType & operator*()
Dereferences the pointer.
Definition PointerWithFlags.h:135
const PtrType * operator->() const
Dereferences the pointer.
Definition PointerWithFlags.h:126