ezEngine  Milestone 7
ArrayBase_inl.h
1 
2 template <typename T, typename Derived>
4 {
5  m_pElements = nullptr;
6  m_uiCount = 0;
7 }
8 
9 template <typename T, typename Derived>
11 {
12  EZ_ASSERT_DEBUG(m_uiCount == 0, "The derived class did not destruct all objects. Count is %i.", m_uiCount);
13  EZ_ASSERT_DEBUG(m_pElements == nullptr, "The derived class did not free its memory.");
14 }
15 
16 template <typename T, typename Derived>
18 {
19  if (this->GetData() == rhs.GetPtr())
20  return;
21 
22  const ezUInt32 uiOldCount = m_uiCount;
23  const ezUInt32 uiNewCount = rhs.GetCount();
24 
25  if (uiNewCount > uiOldCount)
26  {
27  static_cast<Derived*>(this)->Reserve(uiNewCount);
28  ezMemoryUtils::Copy(m_pElements, rhs.GetPtr(), uiOldCount);
29  ezMemoryUtils::CopyConstruct(m_pElements + uiOldCount, rhs.GetPtr() + uiOldCount, uiNewCount - uiOldCount);
30  }
31  else
32  {
33  ezMemoryUtils::Copy(m_pElements, rhs.GetPtr(), uiNewCount);
34  ezMemoryUtils::Destruct(m_pElements + uiNewCount, uiOldCount - uiNewCount);
35  }
36 
37  m_uiCount = uiNewCount;
38 }
39 
40 template <typename T, typename Derived>
42 {
43  return ezArrayPtr<const T>(m_pElements, m_uiCount);
44 }
45 
46 template <typename T, typename Derived>
48 {
49  return ezArrayPtr<T>(m_pElements, m_uiCount);
50 }
51 
52 template <typename T, typename Derived>
54 {
55  if (m_uiCount != rhs.GetCount())
56  return false;
57 
58  return ezMemoryUtils::IsEqual(m_pElements, rhs.GetPtr(), m_uiCount);
59 }
60 
61 template <typename T, typename Derived>
62 EZ_FORCE_INLINE bool ezArrayBase<T, Derived>::operator!= (const ezArrayPtr<const T>& rhs) const
63 {
64  return !(*this == rhs);
65 }
66 
67 template <typename T, typename Derived>
68 EZ_FORCE_INLINE const T& ezArrayBase<T, Derived>::operator[](const ezUInt32 uiIndex) const
69 {
70  EZ_ASSERT_DEV(uiIndex < m_uiCount, "Out of bounds access. Array has %i elements, trying to access element at index %i.", m_uiCount, uiIndex);
71  return m_pElements[uiIndex];
72 }
73 
74 template <typename T, typename Derived>
75 EZ_FORCE_INLINE T& ezArrayBase<T, Derived>::operator[](const ezUInt32 uiIndex)
76 {
77  EZ_ASSERT_DEV(uiIndex < m_uiCount, "Out of bounds access. Array has %i elements, trying to access element at index %i.", m_uiCount, uiIndex);
78  return m_pElements[uiIndex];
79 }
80 
81 template <typename T, typename Derived>
82 void ezArrayBase<T, Derived>::SetCount(ezUInt32 uiCount)
83 {
84  const ezUInt32 uiOldCount = m_uiCount;
85  const ezUInt32 uiNewCount = uiCount;
86 
87  if (uiNewCount > uiOldCount)
88  {
89  static_cast<Derived*>(this)->Reserve(uiNewCount);
90  ezMemoryUtils::DefaultConstruct(m_pElements + uiOldCount, uiNewCount - uiOldCount);
91  }
92  else if (uiNewCount < uiOldCount)
93  {
94  ezMemoryUtils::Destruct(m_pElements + uiNewCount, uiOldCount - uiNewCount);
95  }
96 
97  m_uiCount = uiCount;
98 }
99 
100 template <typename T, typename Derived>
102 {
103  const ezUInt32 uiOldCount = m_uiCount;
104  const ezUInt32 uiNewCount = uiCount;
105 
106  if (uiNewCount > uiOldCount)
107  {
108  static_cast<Derived*>(this)->Reserve(uiNewCount);
109  ezMemoryUtils::Construct(m_pElements + uiOldCount, uiNewCount - uiOldCount);
110  }
111  else if (uiNewCount < uiOldCount)
112  {
113  ezMemoryUtils::Destruct(m_pElements + uiNewCount, uiOldCount - uiNewCount);
114  }
115 
116  m_uiCount = uiCount;
117 }
118 
119 template <typename T, typename Derived>
120 EZ_FORCE_INLINE ezUInt32 ezArrayBase<T, Derived>::GetCount() const
121 {
122  return m_uiCount;
123 }
124 
125 template <typename T, typename Derived>
126 EZ_FORCE_INLINE bool ezArrayBase<T, Derived>::IsEmpty() const
127 {
128  return m_uiCount == 0;
129 }
130 
131 template <typename T, typename Derived>
133 {
134  ezMemoryUtils::Destruct(m_pElements, m_uiCount);
135  m_uiCount = 0;
136 }
137 
138 template <typename T, typename Derived>
139 bool ezArrayBase<T, Derived>::Contains(const T& value) const
140 {
141  return IndexOf(value) != ezInvalidIndex;
142 }
143 
144 template <typename T, typename Derived>
145 void ezArrayBase<T, Derived>::Insert(const T& value, ezUInt32 uiIndex)
146 {
147  EZ_ASSERT_DEV(uiIndex <= m_uiCount, "Invalid index. Array has %i elements, trying to insert element at index %i.", m_uiCount, uiIndex);
148 
149  static_cast<Derived*>(this)->Reserve(m_uiCount + 1);
150 
151  ezMemoryUtils::Prepend(m_pElements + uiIndex, value, m_uiCount - uiIndex);
152  m_uiCount++;
153 }
154 
155 template <typename T, typename Derived>
156 void ezArrayBase<T, Derived>::Insert(T&& value, ezUInt32 uiIndex)
157 {
158  EZ_ASSERT_DEV(uiIndex <= m_uiCount, "Invalid index. Array has %i elements, trying to insert element at index %i.", m_uiCount, uiIndex);
159 
160  static_cast<Derived*>(this)->Reserve(m_uiCount + 1);
161 
162  ezMemoryUtils::Prepend(m_pElements + uiIndex, std::move(value), m_uiCount - uiIndex);
163  m_uiCount++;
164 }
165 
166 template <typename T, typename Derived>
168 {
169  ezUInt32 uiIndex = IndexOf(value);
170 
171  if (uiIndex == ezInvalidIndex)
172  return false;
173 
174  RemoveAt(uiIndex);
175  return true;
176 }
177 
178 template <typename T, typename Derived>
180 {
181  ezUInt32 uiIndex = IndexOf(value);
182 
183  if (uiIndex == ezInvalidIndex)
184  return false;
185 
186  RemoveAtSwap(uiIndex);
187  return true;
188 }
189 
190 template <typename T, typename Derived>
191 void ezArrayBase<T, Derived>::RemoveAt(ezUInt32 uiIndex)
192 {
193  EZ_ASSERT_DEV(uiIndex < m_uiCount, "Out of bounds access. Array has %i elements, trying to remove element at index %i.", m_uiCount, uiIndex);
194 
195  m_uiCount--;
196  ezMemoryUtils::RelocateOverlapped(m_pElements + uiIndex, m_pElements + uiIndex + 1, m_uiCount - uiIndex);
197 }
198 
199 template <typename T, typename Derived>
201 {
202  EZ_ASSERT_DEV(uiIndex < m_uiCount, "Out of bounds access. Array has %i elements, trying to remove element at index %i.", m_uiCount, uiIndex);
203 
204  m_uiCount--;
205  if (m_uiCount != uiIndex)
206  {
207  m_pElements[uiIndex] = std::move(m_pElements[m_uiCount]);
208  }
209  ezMemoryUtils::Destruct(m_pElements + m_uiCount, 1);
210 }
211 
212 template <typename T, typename Derived>
213 ezUInt32 ezArrayBase<T, Derived>::IndexOf(const T& value, ezUInt32 uiStartIndex) const
214 {
215  for (ezUInt32 i = uiStartIndex; i < m_uiCount; i++)
216  {
217  if (ezMemoryUtils::IsEqual(m_pElements + i, &value))
218  return i;
219  }
220  return ezInvalidIndex;
221 }
222 
223 template <typename T, typename Derived>
224 ezUInt32 ezArrayBase<T, Derived>::LastIndexOf(const T& value, ezUInt32 uiStartIndex) const
225 {
226  for (ezUInt32 i = ezMath::Min(uiStartIndex, m_uiCount); i-- > 0;)
227  {
228  if (ezMemoryUtils::IsEqual(m_pElements + i, &value))
229  return i;
230  }
231  return ezInvalidIndex;
232 }
233 
234 template <typename T, typename Derived>
236 {
237  static_cast<Derived*>(this)->Reserve(m_uiCount + 1);
238 
239  ezMemoryUtils::Construct(m_pElements + m_uiCount, 1);
240 
241  T& ReturnRef = *(m_pElements + m_uiCount);
242 
243  m_uiCount++;
244 
245  return ReturnRef;
246 }
247 
248 template <typename T, typename Derived>
250 {
251  static_cast<Derived*>(this)->Reserve(m_uiCount + 1);
252 
253  ezMemoryUtils::CopyConstruct(m_pElements + m_uiCount, value, 1);
254  m_uiCount++;
255 }
256 
257 template <typename T, typename Derived>
259 {
260  static_cast<Derived*>(this)->Reserve(m_uiCount + 1);
261 
262  ezMemoryUtils::MoveConstruct<T>(m_pElements + m_uiCount, std::move(value));
263  m_uiCount++;
264 }
265 
266 template <typename T, typename Derived>
268 {
269  EZ_ASSERT_DEV(m_uiCount < m_uiCapacity, "Appending unchecked to array with insufficient capacity.");
270 
271  ezMemoryUtils::CopyConstruct(m_pElements + m_uiCount, value, 1);
272  m_uiCount++;
273 }
274 
275 template <typename T, typename Derived>
277 {
278  EZ_ASSERT_DEV(m_uiCount < m_uiCapacity, "Appending unchecked to array with insufficient capacity.");
279 
280  ezMemoryUtils::MoveConstruct<T>(m_pElements + m_uiCount, std::move(value));
281  m_uiCount++;
282 }
283 
284 template <typename T, typename Derived>
286 {
287  const ezUInt32 uiRangeCount = range.GetCount();
288  static_cast<Derived*>(this)->Reserve(m_uiCount + uiRangeCount);
289 
290  ezMemoryUtils::CopyConstruct(m_pElements + m_uiCount, range.GetPtr(), uiRangeCount);
291  m_uiCount += uiRangeCount;
292 }
293 
294 template <typename T, typename Derived>
295 void ezArrayBase<T, Derived>::PopBack(ezUInt32 uiCountToRemove /* = 1 */)
296 {
297  EZ_ASSERT_DEV(m_uiCount >= uiCountToRemove, "Out of bounds access. Array has %i elements, trying to pop %i elements.", m_uiCount, uiCountToRemove);
298 
299  m_uiCount -= uiCountToRemove;
300  ezMemoryUtils::Destruct(m_pElements + m_uiCount, uiCountToRemove);
301 }
302 
303 template <typename T, typename Derived>
305 {
306  EZ_ASSERT_DEV(m_uiCount > 0, "Out of bounds access. Trying to peek into an empty array.");
307  return m_pElements[m_uiCount - 1];
308 }
309 
310 template <typename T, typename Derived>
311 EZ_FORCE_INLINE const T& ezArrayBase<T, Derived>::PeekBack() const
312 {
313  EZ_ASSERT_DEV(m_uiCount > 0, "Out of bounds access. Trying to peek into an empty array.");
314  return m_pElements[m_uiCount - 1];
315 }
316 
317 template <typename T, typename Derived>
318 template <typename Comparer>
319 void ezArrayBase<T, Derived>::Sort(const Comparer& comparer)
320 {
321  if (m_uiCount > 1)
322  {
323  ezArrayPtr<T> ar = *this;
324  ezSorting::QuickSort(ar, comparer);
325  }
326 }
327 
328 template <typename T, typename Derived>
330 {
331  if (m_uiCount > 1)
332  {
333  ezArrayPtr<T> ar = *this;
335  }
336 }
337 
338 template <typename T, typename Derived>
340 {
341  if (IsEmpty())
342  return nullptr;
343 
344  return m_pElements;
345 }
346 
347 template <typename T, typename Derived>
349 {
350  if (IsEmpty())
351  return nullptr;
352 
353  return m_pElements;
354 }
355 
356 template <typename T, typename Derived>
358 {
359  return ezArrayPtr<T>(GetData(), GetCount());
360 }
361 
362 template <typename T, typename Derived>
364 {
365  return ezArrayPtr<const T>(GetData(), GetCount());
366 }