Plasma Engine  2.0
Loading...
Searching...
No Matches
ArrayPtr.h
1#pragma once
2
3#include <Foundation/Memory/MemoryUtils.h>
4
5#include <Foundation/Containers/Implementation/ArrayIterator.h>
6
7// This #include is quite vital, do not remove it!
8#include <Foundation/Strings/FormatString.h>
9
10#include <Foundation/Math/Math.h>
11
13#ifndef plInvalidIndex
14# define plInvalidIndex 0xFFFFFFFF
15#endif
16
17namespace plArrayPtrDetail
18{
19 template <typename U>
21 {
22 using type = plUInt8;
23 };
24
25 template <typename U>
26 struct ByteTypeHelper<const U>
27 {
28 using type = const plUInt8;
29 };
30} // namespace plArrayPtrDetail
31
35template <typename T>
37{
38 template <typename U>
39 friend class plArrayPtr;
40
41public:
42 PL_DECLARE_POD_TYPE();
43
44 static_assert(!std::is_same_v<T, void>, "plArrayPtr<void> is not allowed (anymore)");
45 static_assert(!std::is_same_v<T, const void>, "plArrayPtr<void> is not allowed (anymore)");
46
47 using ByteType = typename plArrayPtrDetail::ByteTypeHelper<T>::type;
48 using ValueType = T;
49 using PointerType = T*;
50
52 PL_ALWAYS_INLINE plArrayPtr() // [tested]
53 : m_pPtr(nullptr)
54 , m_uiCount(0u)
55 {
56 }
57
59 PL_ALWAYS_INLINE plArrayPtr(const plArrayPtr<T>& other) // [tested]
60 {
61 m_pPtr = other.m_pPtr;
62 m_uiCount = other.m_uiCount;
63 }
64
66 inline plArrayPtr(T* pPtr, plUInt32 uiCount) // [tested]
67 : m_pPtr(pPtr)
68 , m_uiCount(uiCount)
69 {
70 // If any of the arguments is invalid, we invalidate ourself.
71 if (m_pPtr == nullptr || m_uiCount == 0)
72 {
73 m_pPtr = nullptr;
74 m_uiCount = 0;
75 }
76 }
77
79 template <size_t N>
80 PL_ALWAYS_INLINE plArrayPtr(T (&staticArray)[N]) // [tested]
81 : m_pPtr(staticArray)
82 , m_uiCount(static_cast<plUInt32>(N))
83 {
84 }
85
87 template <typename U>
88 PL_ALWAYS_INLINE plArrayPtr(const plArrayPtr<U>& other) // [tested]
89 : m_pPtr(other.m_pPtr)
90 , m_uiCount(other.m_uiCount)
91 {
92 }
93
95 operator plArrayPtr<const T>() const { return plArrayPtr<const T>(static_cast<const T*>(GetPtr()), GetCount()); } // [tested]
96
98 PL_ALWAYS_INLINE void operator=(const plArrayPtr<T>& other) // [tested]
99 {
100 m_pPtr = other.m_pPtr;
101 m_uiCount = other.m_uiCount;
102 }
103
105 PL_ALWAYS_INLINE void Clear()
106 {
107 m_pPtr = nullptr;
108 m_uiCount = 0;
109 }
110
111 PL_ALWAYS_INLINE void operator=(std::nullptr_t) // [tested]
112 {
113 m_pPtr = nullptr;
114 m_uiCount = 0;
115 }
116
118 PL_ALWAYS_INLINE PointerType GetPtr() const // [tested]
119 {
120 return m_pPtr;
121 }
122
124 PL_ALWAYS_INLINE PointerType GetPtr() // [tested]
125 {
126 return m_pPtr;
127 }
128
130 PL_ALWAYS_INLINE PointerType GetEndPtr() { return m_pPtr + m_uiCount; }
131
133 PL_ALWAYS_INLINE PointerType GetEndPtr() const { return m_pPtr + m_uiCount; }
134
136 PL_ALWAYS_INLINE bool IsEmpty() const // [tested]
137 {
138 return GetCount() == 0;
139 }
140
142 PL_ALWAYS_INLINE plUInt32 GetCount() const // [tested]
143 {
144 return m_uiCount;
145 }
146
148 PL_FORCE_INLINE plArrayPtr<T> GetSubArray(plUInt32 uiStart, plUInt32 uiCount) const // [tested]
149 {
150 // the first check is necessary to also detect errors when uiStart+uiCount would overflow
151 PL_ASSERT_DEV(uiStart <= GetCount() && uiStart + uiCount <= GetCount(), "uiStart+uiCount ({0}) has to be smaller or equal than the count ({1}).",
152 uiStart + uiCount, GetCount());
153 return plArrayPtr<T>(GetPtr() + uiStart, uiCount);
154 }
155
158 PL_FORCE_INLINE plArrayPtr<T> GetSubArray(plUInt32 uiStart) const // [tested]
159 {
160 PL_ASSERT_DEV(uiStart <= GetCount(), "uiStart ({0}) has to be smaller or equal than the count ({1}).", uiStart, GetCount());
161 return plArrayPtr<T>(GetPtr() + uiStart, GetCount() - uiStart);
162 }
163
166 {
167 return plArrayPtr<const ByteType>(reinterpret_cast<const ByteType*>(GetPtr()), GetCount() * sizeof(T));
168 }
169
171 PL_ALWAYS_INLINE plArrayPtr<ByteType> ToByteArray() { return plArrayPtr<ByteType>(reinterpret_cast<ByteType*>(GetPtr()), GetCount() * sizeof(T)); }
172
173
175 template <typename U>
176 PL_ALWAYS_INLINE plArrayPtr<U> Cast()
177 {
178 static_assert(sizeof(T) == sizeof(U), "Can only cast with equivalent element size.");
179 return plArrayPtr<U>(reinterpret_cast<U*>(GetPtr()), GetCount());
180 }
181
183 template <typename U>
184 PL_ALWAYS_INLINE plArrayPtr<const U> Cast() const
185 {
186 static_assert(sizeof(T) == sizeof(U), "Can only cast with equivalent element size.");
187 return plArrayPtr<const U>(reinterpret_cast<const U*>(GetPtr()), GetCount());
188 }
189
191 PL_FORCE_INLINE const ValueType& operator[](plUInt32 uiIndex) const // [tested]
192 {
193 PL_ASSERT_DEBUG(uiIndex < GetCount(), "Cannot access element {0}, the array only holds {1} elements.", uiIndex, GetCount());
194 return *static_cast<const ValueType*>(GetPtr() + uiIndex);
195 }
196
198 PL_FORCE_INLINE ValueType& operator[](plUInt32 uiIndex) // [tested]
199 {
200 PL_ASSERT_DEBUG(uiIndex < GetCount(), "Cannot access element {0}, the array only holds {1} elements.", uiIndex, GetCount());
201 return *static_cast<ValueType*>(GetPtr() + uiIndex);
202 }
203
205 template <typename = typename std::enable_if<std::is_const<T>::value == false>>
206 inline bool operator==(const plArrayPtr<const T>& other) const // [tested]
207 {
208 if (GetCount() != other.GetCount())
209 return false;
210
211 if (GetPtr() == other.GetPtr())
212 return true;
213
214 return plMemoryUtils::IsEqual(static_cast<const ValueType*>(GetPtr()), static_cast<const ValueType*>(other.GetPtr()), GetCount());
215 }
216
217#if PL_DISABLED(PL_USE_CPP20_OPERATORS)
218 template <typename = typename std::enable_if<std::is_const<T>::value == false>>
219 inline bool operator!=(const plArrayPtr<const T>& other) const // [tested]
220 {
221 return !(*this == other);
222 }
223#endif
224
226 inline bool operator==(const plArrayPtr<T>& other) const // [tested]
227 {
228 if (GetCount() != other.GetCount())
229 return false;
230
231 if (GetPtr() == other.GetPtr())
232 return true;
233
234 return plMemoryUtils::IsEqual(static_cast<const ValueType*>(GetPtr()), static_cast<const ValueType*>(other.GetPtr()), GetCount());
235 }
236 PL_ADD_DEFAULT_OPERATOR_NOTEQUAL(const plArrayPtr<T>&);
237
239 inline bool operator<(const plArrayPtr<const T>& other) const // [tested]
240 {
241 if (GetCount() != other.GetCount())
242 return GetCount() < other.GetCount();
243
244 for (plUInt32 i = 0; i < GetCount(); ++i)
245 {
246 if (GetPtr()[i] < other.GetPtr()[i])
247 return true;
248
249 if (other.GetPtr()[i] < GetPtr()[i])
250 return false;
251 }
252
253 return false;
254 }
255
257 inline void CopyFrom(const plArrayPtr<const T>& other) // [tested]
258 {
259 PL_ASSERT_DEV(GetCount() == other.GetCount(), "Count for copy does not match. Target has {0} elements, source {1} elements", GetCount(), other.GetCount());
260
261 plMemoryUtils::Copy(static_cast<ValueType*>(GetPtr()), static_cast<const ValueType*>(other.GetPtr()), GetCount());
262 }
263
264 PL_ALWAYS_INLINE void Swap(plArrayPtr<T>& other)
265 {
266 ::plMath::Swap(m_pPtr, other.m_pPtr);
267 ::plMath::Swap(m_uiCount, other.m_uiCount);
268 }
269
271 PL_ALWAYS_INLINE bool Contains(const T& value) const // [tested]
272 {
273 return IndexOf(value) != plInvalidIndex;
274 }
275
277 inline plUInt32 IndexOf(const T& value, plUInt32 uiStartIndex = 0) const // [tested]
278 {
279 for (plUInt32 i = uiStartIndex; i < m_uiCount; ++i)
280 {
281 if (plMemoryUtils::IsEqual(m_pPtr + i, &value))
282 return i;
283 }
284
285 return plInvalidIndex;
286 }
287
289 inline plUInt32 LastIndexOf(const T& value, plUInt32 uiStartIndex = plInvalidIndex) const // [tested]
290 {
291 for (plUInt32 i = ::plMath::Min(uiStartIndex, m_uiCount); i-- > 0;)
292 {
293 if (plMemoryUtils::IsEqual(m_pPtr + i, &value))
294 return i;
295 }
296 return plInvalidIndex;
297 }
298
299 using const_iterator = const T*;
300 using const_reverse_iterator = const_reverse_pointer_iterator<T>;
301 using iterator = T*;
302 using reverse_iterator = reverse_pointer_iterator<T>;
303
304private:
305 PointerType m_pPtr;
306 plUInt32 m_uiCount;
307};
308
310
313
315
317template <typename T>
318PL_ALWAYS_INLINE plArrayPtr<T> plMakeArrayPtr(T* pPtr, plUInt32 uiCount)
319{
320 return plArrayPtr<T>(pPtr, uiCount);
321}
322
324template <typename T, plUInt32 N>
325PL_ALWAYS_INLINE plArrayPtr<T> plMakeArrayPtr(T (&staticArray)[N])
326{
327 return plArrayPtr<T>(staticArray);
328}
329
331template <typename T>
332PL_ALWAYS_INLINE plConstByteArrayPtr plMakeByteArrayPtr(const T* pPtr, plUInt32 uiCount)
333{
334 return plConstByteArrayPtr(static_cast<const plUInt8*>(pPtr), uiCount * sizeof(T));
335}
336
338template <typename T>
339PL_ALWAYS_INLINE plByteArrayPtr plMakeByteArrayPtr(T* pPtr, plUInt32 uiCount)
340{
341 return plByteArrayPtr(reinterpret_cast<plUInt8*>(pPtr), uiCount * sizeof(T));
342}
343
345PL_ALWAYS_INLINE plByteArrayPtr plMakeByteArrayPtr(void* pPtr, plUInt32 uiBytes)
346{
347 return plByteArrayPtr(reinterpret_cast<plUInt8*>(pPtr), uiBytes);
348}
349
351PL_ALWAYS_INLINE plConstByteArrayPtr plMakeByteArrayPtr(const void* pPtr, plUInt32 uiBytes)
352{
353 return plConstByteArrayPtr(static_cast<const plUInt8*>(pPtr), uiBytes);
354}
355
357
358template <typename T>
359typename plArrayPtr<T>::iterator begin(plArrayPtr<T>& ref_container)
360{
361 return ref_container.GetPtr();
362}
363
364template <typename T>
365typename plArrayPtr<T>::const_iterator begin(const plArrayPtr<T>& container)
366{
367 return container.GetPtr();
368}
369
370template <typename T>
371typename plArrayPtr<T>::const_iterator cbegin(const plArrayPtr<T>& container)
372{
373 return container.GetPtr();
374}
375
376template <typename T>
377typename plArrayPtr<T>::reverse_iterator rbegin(plArrayPtr<T>& ref_container)
378{
379 return typename plArrayPtr<T>::reverse_iterator(ref_container.GetPtr() + ref_container.GetCount() - 1);
380}
381
382template <typename T>
383typename plArrayPtr<T>::const_reverse_iterator rbegin(const plArrayPtr<T>& container)
384{
385 return typename plArrayPtr<T>::const_reverse_iterator(container.GetPtr() + container.GetCount() - 1);
386}
387
388template <typename T>
389typename plArrayPtr<T>::const_reverse_iterator crbegin(const plArrayPtr<T>& container)
390{
391 return typename plArrayPtr<T>::const_reverse_iterator(container.GetPtr() + container.GetCount() - 1);
392}
393
394template <typename T>
395typename plArrayPtr<T>::iterator end(plArrayPtr<T>& ref_container)
396{
397 return ref_container.GetPtr() + ref_container.GetCount();
398}
399
400template <typename T>
401typename plArrayPtr<T>::const_iterator end(const plArrayPtr<T>& container)
402{
403 return container.GetPtr() + container.GetCount();
404}
405
406template <typename T>
407typename plArrayPtr<T>::const_iterator cend(const plArrayPtr<T>& container)
408{
409 return container.GetPtr() + container.GetCount();
410}
411
412template <typename T>
413typename plArrayPtr<T>::reverse_iterator rend(plArrayPtr<T>& ref_container)
414{
415 return typename plArrayPtr<T>::reverse_iterator(ref_container.GetPtr() - 1);
416}
417
418template <typename T>
419typename plArrayPtr<T>::const_reverse_iterator rend(const plArrayPtr<T>& container)
420{
421 return typename plArrayPtr<T>::const_reverse_iterator(container.GetPtr() - 1);
422}
423
424template <typename T>
425typename plArrayPtr<T>::const_reverse_iterator crend(const plArrayPtr<T>& container)
426{
427 return typename plArrayPtr<T>::const_reverse_iterator(container.GetPtr() - 1);
428}
This class encapsulates an array and it's size. It is recommended to use this class instead of plain ...
Definition ArrayPtr.h:37
PL_ALWAYS_INLINE plUInt32 GetCount() const
Returns the number of elements in the array.
Definition ArrayPtr.h:142
PL_ALWAYS_INLINE PointerType GetPtr()
Returns the pointer to the array.
Definition ArrayPtr.h:124
void CopyFrom(const plArrayPtr< const T > &other)
Copies the data from other into this array. The arrays must have the exact same size.
Definition ArrayPtr.h:257
PL_FORCE_INLINE ValueType & operator[](plUInt32 uiIndex)
Index access.
Definition ArrayPtr.h:198
PL_ALWAYS_INLINE plArrayPtr< ByteType > ToByteArray()
Reinterprets this array as a byte array.
Definition ArrayPtr.h:171
bool operator<(const plArrayPtr< const T > &other) const
Compares the two arrays for less.
Definition ArrayPtr.h:239
plUInt32 IndexOf(const T &value, plUInt32 uiStartIndex=0) const
Searches for the first occurrence of the given value and returns its index or plInvalidIndex if not f...
Definition ArrayPtr.h:277
PL_ALWAYS_INLINE plArrayPtr(const plArrayPtr< U > &other)
Initializes the plArrayPtr to be a copy of other. No memory is allocated or copied.
Definition ArrayPtr.h:88
PL_ALWAYS_INLINE void operator=(const plArrayPtr< T > &other)
Copies the pointer and size of /a other. Does not allocate any data.
Definition ArrayPtr.h:98
bool operator==(const plArrayPtr< T > &other) const
Compares the two arrays for equality.
Definition ArrayPtr.h:226
PL_ALWAYS_INLINE plArrayPtr< U > Cast()
Cast an ArrayPtr to an ArrayPtr to a different, but same size, type.
Definition ArrayPtr.h:176
PL_ALWAYS_INLINE PointerType GetEndPtr()
Returns the pointer behind the last element of the array.
Definition ArrayPtr.h:130
PL_ALWAYS_INLINE bool Contains(const T &value) const
Checks whether the given value can be found in the array. O(n) complexity.
Definition ArrayPtr.h:271
PL_ALWAYS_INLINE void Clear()
Clears the array.
Definition ArrayPtr.h:105
PL_FORCE_INLINE const ValueType & operator[](plUInt32 uiIndex) const
Index access.
Definition ArrayPtr.h:191
PL_ALWAYS_INLINE PointerType GetPtr() const
Returns the pointer to the array.
Definition ArrayPtr.h:118
PL_ALWAYS_INLINE bool IsEmpty() const
Returns whether the array is empty.
Definition ArrayPtr.h:136
plUInt32 LastIndexOf(const T &value, plUInt32 uiStartIndex=plInvalidIndex) const
Searches for the last occurrence of the given value and returns its index or plInvalidIndex if not fo...
Definition ArrayPtr.h:289
PL_ALWAYS_INLINE plArrayPtr< const ByteType > ToByteArray() const
Reinterprets this array as a byte array.
Definition ArrayPtr.h:165
PL_FORCE_INLINE plArrayPtr< T > GetSubArray(plUInt32 uiStart, plUInt32 uiCount) const
Creates a sub-array from this array.
Definition ArrayPtr.h:148
PL_ALWAYS_INLINE plArrayPtr< const U > Cast() const
Cast an ArrayPtr to an ArrayPtr to a different, but same size, type.
Definition ArrayPtr.h:184
PL_ALWAYS_INLINE plArrayPtr(const plArrayPtr< T > &other)
Copies the pointer and size of /a other. Does not allocate any data.
Definition ArrayPtr.h:59
PL_ALWAYS_INLINE plArrayPtr()
Initializes the plArrayPtr to be empty.
Definition ArrayPtr.h:52
bool operator==(const plArrayPtr< const T > &other) const
Compares the two arrays for equality.
Definition ArrayPtr.h:206
plArrayPtr(T *pPtr, plUInt32 uiCount)
Initializes the plArrayPtr with the given pointer and number of elements. No memory is allocated or c...
Definition ArrayPtr.h:66
PL_ALWAYS_INLINE plArrayPtr(T(&staticArray)[N])
Initializes the plArrayPtr to encapsulate the given array.
Definition ArrayPtr.h:80
PL_ALWAYS_INLINE PointerType GetEndPtr() const
Returns the pointer behind the last element of the array.
Definition ArrayPtr.h:133
PL_FORCE_INLINE plArrayPtr< T > GetSubArray(plUInt32 uiStart) const
Creates a sub-array from this array.
Definition ArrayPtr.h:158
static bool IsEqual(const T *a, const T *b, size_t uiCount=1)
Tests if objects of type T from pSource and pDestination are equal.
static void Copy(T *pDestination, const T *pSource, size_t uiCount=1)
Copies objects of type T from pSource to pDestination.
constexpr PL_ALWAYS_INLINE T Min(T f1, T f2)
Returns the smaller value, f1 or f2.
Definition Math_inl.h:27
PL_ALWAYS_INLINE void Swap(T &ref_f1, T &ref_f2)
Swaps the values in the two variables f1 and f2.
Definition Math_inl.h:224
Base class for Pointer like reverse iterators.
Definition ArrayIterator.h:152
Definition ArrayPtr.h:21
Non-Const class for Pointer like reverse iterators.
Definition ArrayIterator.h:216