ezEngine  Milestone 9
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 namespace ezArrayPtrDetail
11 {
12  template <typename U>
14  {
15  typedef ezUInt8 type;
16  };
17 
18  template <typename U>
19  struct ByteTypeHelper<const U>
20  {
21  typedef const ezUInt8 type;
22  };
23 
26  template <typename U>
28  {
29  public:
30  EZ_DECLARE_POD_TYPE();
31 
32  VoidPtrHelper() {}
33  VoidPtrHelper(U* p)
34  : m_ptr(p)
35  {
36  }
37  operator U*() const { return m_ptr; }
38  template <typename V, typename = std::enable_if_t<sizeof(V) == 1 && !std::is_const<U>::value>>
39  explicit operator V*() const
40  {
41  return static_cast<V*>(m_ptr);
42  }
43  template <typename V, typename = std::enable_if_t<sizeof(V) == 1>>
44  explicit operator const V*() const
45  {
46  return static_cast<const V*>(m_ptr);
47  }
48  U* operator+(ptrdiff_t off) const { return (U*)((ptrdiff_t(m_ptr) + off)); }
49  U* operator-(ptrdiff_t off) const { return (U*)((ptrdiff_t(m_ptr) - off)); }
50  ptrdiff_t operator-(const void* other) const { return ptrdiff_t(m_ptr) - ptrdiff_t(other); }
51 
52  private:
53  U* m_ptr;
54  };
55 
56  template <typename U>
58  {
59  typedef U valueType;
60  typedef U* pointerType;
61  };
62 
63  template<>
64  struct VoidTypeHelper<void>
65  {
66  typedef ezUInt8 valueType;
68  };
69 
70  template <>
71  struct VoidTypeHelper<const void>
72  {
73  typedef const ezUInt8 valueType;
75  };
76 } // namespace ezArrayPtrDetail
77 
81 template <typename T>
83 {
84 public:
85  EZ_DECLARE_POD_TYPE();
86 
87  typedef T ElementType;
88  typedef typename ezTypeTraits<T>::NonConstType MutableElementType;
89 
90 public:
91  typedef typename ezArrayPtrDetail::ByteTypeHelper<T>::type ByteType;
92  typedef typename ezArrayPtrDetail::VoidTypeHelper<T>::valueType ValueType;
93  typedef typename ezArrayPtrDetail::VoidTypeHelper<T>::pointerType PointerType;
94 
96  EZ_ALWAYS_INLINE ezArrayPtr() // [tested]
97  : m_ptr(nullptr)
98  , m_uiCount(0u)
99  {
100  }
101 
105  template <typename U, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value ||
106  sizeof(typename ezArrayPtrDetail::VoidTypeHelper<U>::valueType) == 1>>
107  inline ezArrayPtr(U* ptr, ezUInt32 uiCount) // [tested]
108  : m_ptr(ptr)
109  , m_uiCount(uiCount)
110  {
111  // If any of the arguments is invalid, we invalidate ourself.
112  if (m_ptr == nullptr || m_uiCount == 0)
113  {
114  m_ptr = nullptr;
115  m_uiCount = 0;
116  }
117  }
118 
120  template <size_t N>
121  EZ_ALWAYS_INLINE ezArrayPtr(ValueType (&staticArray)[N]) // [tested]
122  : m_ptr(staticArray)
123  , m_uiCount(static_cast<ezUInt32>(N))
124  {
125  }
126 
128  EZ_ALWAYS_INLINE ezArrayPtr(const ezArrayPtr<T>& other) // [tested]
129  : m_ptr(other.m_ptr)
130  , m_uiCount(other.m_uiCount)
131  {
132  }
133 
135  operator ezArrayPtr<const T>() const { return ezArrayPtr<const T>(static_cast<const T*>(GetPtr()), GetCount()); } // [tested]
136 
138  EZ_ALWAYS_INLINE void operator=(const ezArrayPtr<T>& other) // [tested]
139  {
140  m_ptr = other.m_ptr;
141  m_uiCount = other.m_uiCount;
142  }
143 
145  EZ_ALWAYS_INLINE void Clear()
146  {
147  m_ptr = nullptr;
148  m_uiCount = 0;
149  }
150 
151  EZ_ALWAYS_INLINE void operator=(std::nullptr_t) // [tested]
152  {
153  m_ptr = nullptr;
154  m_uiCount = 0;
155  }
156 
158  EZ_ALWAYS_INLINE const PointerType GetPtr() const // [tested]
159  {
160  return m_ptr;
161  }
162 
164  EZ_ALWAYS_INLINE PointerType GetPtr() // [tested]
165  {
166  return m_ptr;
167  }
168 
170  EZ_ALWAYS_INLINE PointerType GetEndPtr() { return m_ptr + m_uiCount; }
171 
173  EZ_ALWAYS_INLINE const PointerType GetEndPtr() const { return m_ptr + m_uiCount; }
174 
176  EZ_ALWAYS_INLINE bool IsEmpty() const // [tested]
177  {
178  return GetCount() == 0;
179  }
180 
182  EZ_ALWAYS_INLINE ezUInt32 GetCount() const // [tested]
183  {
184  return m_uiCount;
185  }
186 
188  EZ_FORCE_INLINE ezArrayPtr<const T> GetSubArray(ezUInt32 uiStart, ezUInt32 uiCount) const // [tested]
189  {
190  EZ_ASSERT_DEV(uiStart + uiCount <= GetCount(), "uiStart+uiCount ({0}) has to be smaller or equal than the count ({1}).",
191  uiStart + uiCount, GetCount());
192  return ezArrayPtr<const T>(GetPtr() + uiStart, uiCount);
193  }
194 
196  EZ_FORCE_INLINE ezArrayPtr<T> GetSubArray(ezUInt32 uiStart, ezUInt32 uiCount) // [tested]
197  {
198  EZ_ASSERT_DEV(uiStart + uiCount <= GetCount(), "uiStart+uiCount ({0}) has to be smaller or equal than the count ({1}).",
199  uiStart + uiCount, GetCount());
200  return ezArrayPtr<T>(GetPtr() + uiStart, uiCount);
201  }
202 
205  EZ_FORCE_INLINE ezArrayPtr<const T> GetSubArray(ezUInt32 uiStart) const // [tested]
206  {
207  EZ_ASSERT_DEV(uiStart <= GetCount(), "uiStart ({0}) has to be smaller or equal than the count ({1}).", uiStart, GetCount());
208  return ezArrayPtr<const T>(GetPtr() + uiStart, GetCount() - uiStart);
209  }
210 
213  EZ_FORCE_INLINE ezArrayPtr<T> GetSubArray(ezUInt32 uiStart) // [tested]
214  {
215  EZ_ASSERT_DEV(uiStart <= GetCount(), "uiStart ({0}) has to be smaller or equal than the count ({1}).", uiStart, GetCount());
216  return ezArrayPtr<T>(GetPtr() + uiStart, GetCount() - uiStart);
217  }
218 
220  EZ_ALWAYS_INLINE ezArrayPtr<const ByteType> ToByteArray() const
221  {
222  return ezArrayPtr<const ByteType>(reinterpret_cast<const ByteType*>(GetPtr()), GetCount() * sizeof(T));
223  }
224 
227  {
228  return ezArrayPtr<ByteType>(reinterpret_cast<ByteType*>(GetPtr()), GetCount() * sizeof(T));
229  }
230 
232  template <typename U>
233  EZ_ALWAYS_INLINE ezArrayPtr<U> Cast()
234  {
235  static_assert(sizeof(T) == sizeof(U), "Can only cast with equivalent element size.");
236  return ezArrayPtr<U>(reinterpret_cast<U*>(GetPtr()), GetCount());
237  }
238 
240  template <typename U>
241  EZ_ALWAYS_INLINE ezArrayPtr<const U> Cast() const
242  {
243  static_assert(sizeof(T) == sizeof(U), "Can only cast with equivalent element size.");
244  return ezArrayPtr<const U>(reinterpret_cast<const U*>(GetPtr()), GetCount());
245  }
246 
248  EZ_FORCE_INLINE const ValueType& operator[](ezUInt32 uiIndex) const // [tested]
249  {
250  EZ_ASSERT_DEV(uiIndex < GetCount(), "Cannot access element {0}, the array only holds {1} elements.", uiIndex, GetCount());
251  return *static_cast<const ValueType*>(GetPtr() + uiIndex);
252  }
253 
255  EZ_FORCE_INLINE ValueType& operator[](ezUInt32 uiIndex) // [tested]
256  {
257  EZ_ASSERT_DEV(uiIndex < GetCount(), "Cannot access element {0}, the array only holds {1} elements.", uiIndex, GetCount());
258  return *static_cast<ValueType*>(GetPtr() + uiIndex);
259  }
260 
262  inline bool operator==(const ezArrayPtr<const T>& other) const // [tested]
263  {
264  if (GetCount() != other.GetCount())
265  return false;
266 
267  if (GetPtr() == other.GetPtr())
268  return true;
269 
270  return ezMemoryUtils::IsEqual(static_cast<const ValueType*>(GetPtr()), static_cast<const ValueType*>(other.GetPtr()), GetCount());
271  }
272 
274  EZ_ALWAYS_INLINE bool operator!=(const ezArrayPtr<const T>& other) const // [tested]
275  {
276  return !(*this == other);
277  }
278 
280  inline void CopyFrom(const ezArrayPtr<const T>& other) // [tested]
281  {
282  EZ_ASSERT_DEV(GetCount() == other.GetCount(), "Count for copy does not match. Target has {0} elements, source {1} elements", GetCount(),
283  other.GetCount());
284 
285  ezMemoryUtils::Copy(static_cast<ValueType*>(GetPtr()), static_cast<const ValueType*>(other.GetPtr()), GetCount());
286  }
287 
288  EZ_ALWAYS_INLINE void Swap(ezArrayPtr<T>& other)
289  {
290  ezMath::Swap(m_ptr, other.m_ptr);
291  ezMath::Swap(m_uiCount, other.m_uiCount);
292  }
293 
294  typedef const T* const_iterator;
295  typedef const_reverse_pointer_iterator<T> const_reverse_iterator;
296  typedef T* iterator;
297  typedef reverse_pointer_iterator<T> reverse_iterator;
298 
299 private:
300  PointerType m_ptr;
301  ezUInt32 m_uiCount;
302 };
303 
305 template <typename T>
306 EZ_ALWAYS_INLINE ezArrayPtr<T> ezMakeArrayPtr(T* ptr, ezUInt32 uiCount)
307 {
308  return ezArrayPtr<T>(ptr, uiCount);
309 }
310 
312 template <typename T, ezUInt32 N>
313 EZ_ALWAYS_INLINE ezArrayPtr<T> ezMakeArrayPtr(T (&staticArray)[N])
314 {
315  return ezArrayPtr<T>(staticArray);
316 }
317 
318 template <typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value>>
319 typename ezArrayPtr<T>::iterator begin(ezArrayPtr<T>& container)
320 {
321  return container.GetPtr();
322 }
323 
324 template <typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value>>
325 typename ezArrayPtr<T>::const_iterator begin(const ezArrayPtr<T>& container)
326 {
327  return container.GetPtr();
328 }
329 
330 template <typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value>>
331 typename ezArrayPtr<T>::const_iterator cbegin(const ezArrayPtr<T>& container)
332 {
333  return container.GetPtr();
334 }
335 
336 template <typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value>>
337 typename ezArrayPtr<T>::reverse_iterator rbegin(ezArrayPtr<T>& container)
338 {
339  return typename ezArrayPtr<T>::reverse_iterator(container.GetPtr() + container.GetCount() - 1);
340 }
341 
342 template <typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value>>
343 typename ezArrayPtr<T>::const_reverse_iterator rbegin(const ezArrayPtr<T>& container)
344 {
345  return typename ezArrayPtr<T>::const_reverse_iterator(container.GetPtr() + container.GetCount() - 1);
346 }
347 
348 template <typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value>>
349 typename ezArrayPtr<T>::const_reverse_iterator crbegin(const ezArrayPtr<T>& container)
350 {
351  return typename ezArrayPtr<T>::const_reverse_iterator(container.GetPtr() + container.GetCount() - 1);
352 }
353 
354 template <typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value>>
355 typename ezArrayPtr<T>::iterator end(ezArrayPtr<T>& container)
356 {
357  return container.GetPtr() + container.GetCount();
358 }
359 
360 template <typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value>>
361 typename ezArrayPtr<T>::const_iterator end(const ezArrayPtr<T>& container)
362 {
363  return container.GetPtr() + container.GetCount();
364 }
365 
366 template <typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value>>
367 typename ezArrayPtr<T>::const_iterator cend(const ezArrayPtr<T>& container)
368 {
369  return container.GetPtr() + container.GetCount();
370 }
371 
372 template <typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value>>
373 typename ezArrayPtr<T>::reverse_iterator rend(ezArrayPtr<T>& container)
374 {
375  return typename ezArrayPtr<T>::reverse_iterator(container.GetPtr() - 1);
376 }
377 
378 template <typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value>>
379 typename ezArrayPtr<T>::const_reverse_iterator rend(const ezArrayPtr<T>& container)
380 {
381  return typename ezArrayPtr<T>::const_reverse_iterator(container.GetPtr() - 1);
382 }
383 
384 template <typename T, typename = std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value>>
385 typename ezArrayPtr<T>::const_reverse_iterator crend(const ezArrayPtr<T>& container)
386 {
387  return typename ezArrayPtr<T>::const_reverse_iterator(container.GetPtr() - 1);
388 }
389 
EZ_ALWAYS_INLINE void Swap(T &f1, T &f2)
Swaps the values in the two variables f1 and f2.
Definition: Math_inl.h:112
Helper to allow simple pointer arithmetic in case the ArrayPtr&#39;s type is is void or const void...
Definition: ArrayPtr.h:27
EZ_ALWAYS_INLINE const PointerType GetEndPtr() const
Returns the pointer behind the last element of the array.
Definition: ArrayPtr.h:173
Definition: ArrayPtr.h:10
EZ_FORCE_INLINE ezArrayPtr< T > GetSubArray(ezUInt32 uiStart)
Creates a sub-array from this array.
Definition: ArrayPtr.h:213
EZ_ALWAYS_INLINE ezArrayPtr< ByteType > ToByteArray()
Reinterprets this array as a byte array.
Definition: ArrayPtr.h:226
EZ_ALWAYS_INLINE ezArrayPtr< const ByteType > ToByteArray() const
Reinterprets this array as a byte array.
Definition: ArrayPtr.h:220
std::remove_const< T >::type NonConstType
removes const qualifier
Definition: TypeTraits.h:187
EZ_FORCE_INLINE ezArrayPtr< const T > GetSubArray(ezUInt32 uiStart, ezUInt32 uiCount) const
Creates a sub-array from this array.
Definition: ArrayPtr.h:188
EZ_FORCE_INLINE ValueType & operator[](ezUInt32 uiIndex)
Index access.
Definition: ArrayPtr.h:255
EZ_ALWAYS_INLINE ezArrayPtr< U > Cast()
Cast an ArrayPtr to an ArrayPtr to a different, but same size, type.
Definition: ArrayPtr.h:233
void CopyFrom(const ezArrayPtr< const T > &other)
Copies the data from other into this array. The arrays must have the exact same size.
Definition: ArrayPtr.h:280
EZ_ALWAYS_INLINE void Clear()
Clears the array.
Definition: ArrayPtr.h:145
Definition: ArrayPtr.h:57
Definition: ArrayPtr.h:13
#define EZ_ASSERT_DEV(bCondition, szErrorMsg,...)
Macro to raise an error, if a condition is not met.
Definition: Assert.h:116
EZ_ALWAYS_INLINE bool operator!=(const ezArrayPtr< const T > &other) const
Compares the two arrays for inequality.
Definition: ArrayPtr.h:274
EZ_ALWAYS_INLINE void operator=(const ezArrayPtr< T > &other)
Copies the pointer and size of /a other. Does not allocate any data.
Definition: ArrayPtr.h:138
EZ_ALWAYS_INLINE ezUInt32 GetCount() const
Returns the number of elements in the array.
Definition: ArrayPtr.h:182
EZ_ALWAYS_INLINE bool IsEmpty() const
Returns whether the array is empty.
Definition: ArrayPtr.h:176
Base class for Pointer like reverse iterators.
Definition: ArrayIterator.h:133
EZ_FORCE_INLINE const ValueType & operator[](ezUInt32 uiIndex) const
Index access.
Definition: ArrayPtr.h:248
EZ_ALWAYS_INLINE ezArrayPtr(ValueType(&staticArray)[N])
Initializes the ezArrayPtr to encapsulate the given array.
Definition: ArrayPtr.h:121
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.
ezArrayPtr(U *ptr, ezUInt32 uiCount)
Initializes the ezArrayPtr with the given pointer and number of elements. No memory is allocated or c...
Definition: ArrayPtr.h:107
static void Copy(T *pDestination, const T *pSource, size_t uiCount)
Copies objects of type T from pSource to pDestination.
EZ_ALWAYS_INLINE PointerType GetEndPtr()
Returns the pointer behind the last element of the array.
Definition: ArrayPtr.h:170
EZ_ALWAYS_INLINE const PointerType GetPtr() const
Returns the pointer to the array.
Definition: ArrayPtr.h:158
bool operator==(const ezArrayPtr< const T > &other) const
Compares the two arrays for equality.
Definition: ArrayPtr.h:262
EZ_ALWAYS_INLINE ezArrayPtr< const U > Cast() const
Cast an ArrayPtr to an ArrayPtr to a different, but same size, type.
Definition: ArrayPtr.h:241
EZ_FORCE_INLINE ezArrayPtr< T > GetSubArray(ezUInt32 uiStart, ezUInt32 uiCount)
Creates a sub-array from this array.
Definition: ArrayPtr.h:196
EZ_ALWAYS_INLINE ezArrayPtr(const ezArrayPtr< T > &other)
Initializes the ezArrayPtr to be a copy of other. No memory is allocated or copied.
Definition: ArrayPtr.h:128
Non-Const class for Pointer like reverse iterators.
Definition: ArrayIterator.h:192
EZ_FORCE_INLINE ezArrayPtr< const T > GetSubArray(ezUInt32 uiStart) const
Creates a sub-array from this array.
Definition: ArrayPtr.h:205
EZ_ALWAYS_INLINE ezArrayPtr()
Initializes the ezArrayPtr to be empty.
Definition: ArrayPtr.h:96
EZ_ALWAYS_INLINE PointerType GetPtr()
Returns the pointer to the array.
Definition: ArrayPtr.h:164
This class encapsulates an array and it&#39;s size. It is recommended to use this class instead of plain ...
Definition: ArrayPtr.h:82