OpenBarnyard
 
Loading...
Searching...
No Matches
T2DynamicVector.h
Go to the documentation of this file.
1
11
12#pragma once
13#include "Toshi/T2Allocator.h"
14
16
18{
19protected:
20 T2GenericDynamicVector( T2Allocator* a_pAllocator, TINT a_iInitialSize, TINT a_iGrowSize, TINT a_iElementSize )
21 {
22 m_pAllocator = a_pAllocator;
23 m_iGrowSize = a_iGrowSize;
25 m_iAllocSize = a_iInitialSize;
26 m_poElements = ( a_iInitialSize > 0 ) ? a_pAllocator->Malloc( a_iInitialSize * a_iElementSize ) : TNULL;
27 }
28
29 T2GenericDynamicVector( void* a_poElements, TINT a_iInitialSize, TINT a_iNumElements )
30 {
32 m_iGrowSize = 0;
33 m_iNumElements = a_iNumElements;
34 m_iAllocSize = a_iInitialSize;
35 m_poElements = a_poElements;
36 }
37
38 void Reallocate( TINT a_iNewSize, TINT a_iElementSize );
39 void Grow( TINT a_iNumElements, TINT a_iElementSize );
40
41protected:
46 void* m_poElements; // 0x10
47};
48
49template <class T>
51{
52public:
54 {
55 public:
57
58 public:
59 constexpr Iterator()
60 : m_iIndex( 0 ), m_pVector( TNULL ) {}
61 constexpr Iterator( T2DynamicVector* a_pVector )
62 : m_iIndex( 0 ), m_pVector( a_pVector ) {}
63 constexpr Iterator( T2DynamicVector& a_rVector )
64 : m_iIndex( 0 ), m_pVector( &a_rVector ) {}
65 constexpr Iterator( TINT a_iIndex, T2DynamicVector* a_pVector )
66 : m_iIndex( a_iIndex ), m_pVector( a_pVector ) {}
67 constexpr Iterator( const Iterator& a_rOther )
68 : m_iIndex( a_rOther.m_iIndex ), m_pVector( a_rOther.m_pVector ) {}
69
70 constexpr TINT Index() const
71 {
72 return m_iIndex;
73 }
74
75 TBOOL IsValid() const
76 {
77 return m_pVector && *this != m_pVector->End();
78 }
79
80 T* Get() noexcept
81 {
82 TASSERT( m_iIndex >= 0 );
83 TASSERT( m_pVector );
84 return &m_pVector->At( m_iIndex );
85 }
86
87 const T* Get() const noexcept
88 {
89 TASSERT( m_iIndex >= 0 );
90 TASSERT( m_pVector );
91 return &m_pVector->At( m_iIndex );
92 }
93
94 T& Value()
95 {
96 TASSERT( m_iIndex >= 0 );
97 TASSERT( m_pVector );
98 return m_pVector->At( m_iIndex );
99 }
100
101 const T& Value() const
102 {
103 TASSERT( m_iIndex >= 0 );
104 TASSERT( m_pVector );
105 return m_pVector->At( m_iIndex );
106 }
107
109 {
110 Iterator temp = *this;
111 temp.m_iIndex += 1;
112 return temp;
113 }
114
116 {
117 Iterator temp = *this;
118 temp.m_iIndex -= 1;
119 return temp;
120 }
121
122 operator T*()
123 {
124 return &Value();
125 }
126
127 operator const T*() const
128 {
129 return &Value();
130 }
131
133 {
134 return &Value();
135 }
136
137 const T* operator->() const
138 {
139 return &Value();
140 }
141
142 T& operator*() noexcept
143 {
144 return Value();
145 }
146
147 const T& operator*() const noexcept
148 {
149 return Value();
150 }
151
152 TBOOL operator==( const Iterator& a_rOther ) const noexcept
153 {
154 return a_rOther.m_pVector == m_pVector && a_rOther.m_iIndex == m_iIndex;
155 }
156
157 TBOOL operator>( const Iterator& a_rOther ) const noexcept
158 {
159 return a_rOther.m_pVector == m_pVector && a_rOther.m_iIndex > m_iIndex;
160 }
161
162 TBOOL operator>=( const Iterator& a_rOther ) const noexcept
163 {
164 return a_rOther.m_pVector == m_pVector && a_rOther.m_iIndex >= m_iIndex;
165 }
166
167 TBOOL operator<( const Iterator& a_rOther ) const noexcept
168 {
169 return a_rOther.m_pVector == m_pVector && a_rOther.m_iIndex < m_iIndex;
170 }
171
172 TBOOL operator<=( const Iterator& a_rOther ) const noexcept
173 {
174 return a_rOther.m_pVector == m_pVector && a_rOther.m_iIndex <= m_iIndex;
175 }
176
177 constexpr Iterator& operator=( const Iterator& a_rOther ) noexcept
178 {
179 m_iIndex = a_rOther.m_iIndex;
180 m_pVector = a_rOther.m_pVector;
181 return *this;
182 }
183
185 {
186 m_iIndex++;
187 return *this;
188 }
189
191 {
192 Iterator temp = *this;
193 m_iIndex++;
194 return temp;
195 }
196
198 {
199 m_iIndex--;
200 return *this;
201 }
202
204 {
205 Iterator temp = *this;
206 m_iIndex--;
207 return temp;
208 }
209
210 Iterator operator+( TINT a_iValue ) const
211 {
212 return Iterator( m_iIndex + a_iValue, m_pVector );
213 }
214
215 Iterator operator-( TINT a_iValue ) const
216 {
217 return Iterator( m_iIndex - a_iValue, m_pVector );
218 }
219
220 private:
221 TINT m_iIndex; // 0x0
222 T2DynamicVector* m_pVector; // 0x4
223 };
224
225public:
226 T2DynamicVector( T2Allocator* a_pAllocator = GetGlobalAllocator(), TINT a_iInitialSize = 0, TINT a_iGrowSize = -1 )
227 : T2GenericDynamicVector( a_pAllocator, a_iInitialSize, a_iGrowSize, sizeof( T ) )
228 {}
229
230 T2DynamicVector( T* a_poElements, TINT a_iInitialSize, TINT a_iNumElements )
231 : T2GenericDynamicVector( a_poElements, a_iInitialSize, a_iNumElements )
232 {}
233
235 {
236 FreeMemory();
237 }
238
239 Iterator InsertBefore( Iterator a_itInsertBefore, const T& a_rcItem = T() )
240 {
241 InsertGap( a_itInsertBefore.Index(), 1, sizeof( T ) );
242 TConstruct<T>( &AtUnsafe( a_itInsertBefore.Index() ), a_rcItem );
243
244 return Iterator( a_itInsertBefore.Index(), this );
245 }
246
247 Iterator InsertAfter( Iterator a_itInsertAfter, const T& a_rcItem = T() )
248 {
249 InsertGap( a_itInsertAfter.Index() + 1, 1, sizeof( T ) );
250 TConstruct<T>( &AtUnsafe( a_itInsertAfter.Index() + 1 ), a_rcItem );
251
252 return Iterator( a_itInsertAfter.Index() + 1, this );
253 }
254
255 void Clear()
256 {
257 for ( TINT i = 0; i < m_iNumElements; i++ )
258 {
259 ( (T*)m_poElements + i )->~T();
260 }
261
262 m_iNumElements = 0;
263 }
264
266 {
267 Clear();
268
269 if ( m_pAllocator )
270 Reallocate( 0, sizeof( T ) );
271 else
273 }
274
275 void Reserve( TINT a_iSize )
276 {
277 if ( a_iSize > m_iAllocSize )
278 {
279 Reallocate( a_iSize, sizeof( T ) );
280 }
281 }
282
283 template <class... Args>
284 T* EmplaceBack( Args&&... args )
285 {
286 Grow( 1, sizeof( T ) );
287 return TConstruct<T>( &AtUnsafe( m_iNumElements++ ), std::forward<Args>( args )... );
288 }
289
290 void PushBack( const T& item = T() )
291 {
292 Grow( 1, sizeof( T ) );
293 TConstruct<T>( &AtUnsafe( m_iNumElements++ ), item );
294 }
295
296 void PushBack( T&& item )
297 {
298 Grow( 1, sizeof( T ) );
299 TConstruct<T>( &AtUnsafe( m_iNumElements++ ), item );
300 }
301
302 void PopBack()
303 {
304 TASSERT( m_iNumElements > 0 );
305 AtUnsafe( --m_iNumElements ).~T();
306 }
307
308 Iterator Find( const T& a_rcValue )
309 {
310 for ( auto it = Begin(); it != End(); it++ )
311 {
312 if ( it.Value() == a_rcValue )
313 return it;
314 }
315
316 return End();
317 }
318
319 // Erases element preserving order
320 void Erase( const Iterator& a_rIterator )
321 {
322 TINT uiItemIndex = a_rIterator.Index();
323 TASSERT( uiItemIndex < m_iNumElements );
324
325 AtUnsafe( uiItemIndex ).~T();
326
327 if ( uiItemIndex + 1 < Size() )
328 {
329 for ( TINT i = uiItemIndex + 1; i < Size(); i++ )
330 {
331 TConstruct<T>( &AtUnsafe( i - 1 ), std::move( AtUnsafe( i ) ) );
332 AtUnsafe( i ).~T();
333 }
334 }
335
337 }
338
339 // Finds and erases element preserving order
340 void FindAndErase( const T& a_rcItem )
341 {
342 auto it = Find( a_rcItem );
343
344 if ( it != End() )
345 Erase( it );
346 }
347
348 // Erases element ignoring order but with a faster algorithm
349 void EraseFast( const Iterator& a_rIterator )
350 {
351 TINT uiItemIndex = a_rIterator.Index();
352 TASSERT( uiItemIndex < m_iNumElements );
353
354 AtUnsafe( uiItemIndex ) = Back().Value();
355 PopBack();
356 }
357
358 // Finds and erases element ignoring order but with a faster algorithm
359 void FindAndEraseFast( const T& a_rcItem )
360 {
361 auto it = Find( a_rcItem );
362
363 if ( it != End() )
364 EraseFast( it );
365 }
366
368 {
369 TASSERT( m_iNumElements > 0 );
370 return Iterator( 0, this );
371 }
372
374 {
375 TASSERT( m_iNumElements > 0 );
376 return Iterator( m_iNumElements - 1, this );
377 }
378
380 {
381 return Iterator( 0, this );
382 }
383
385 {
386 return Iterator( m_iNumElements, this );
387 }
388
390 {
391 return Iterator( a_iIndex, this );
392 }
393
394 TINT Size() const
395 {
396 return m_iNumElements;
397 }
398
399 void SetSize( TINT a_iNewSize )
400 {
401 Reserve( a_iNewSize );
402 m_iNumElements = a_iNewSize;
403 }
404
405 void SetSize( TINT a_iNewSize, const T& a_rcValue )
406 {
407 Reserve( a_iNewSize );
408
409 TINT iOldNumElements = m_iNumElements;
410 m_iNumElements = a_iNewSize;
411
412 for ( TINT i = iOldNumElements; i < a_iNewSize; i++ )
413 new ( &AtUnsafe( i ) ) T( a_rcValue );
414 }
415
417 {
418 return m_iAllocSize;
419 }
420
422 {
423 return Size() == 0;
424 }
425
426 T& At( TINT a_iIndex )
427 {
428 TASSERT( a_iIndex < m_iNumElements );
429 return *( TREINTERPRETCAST( T*, m_poElements ) + a_iIndex );
430 }
431
432 const T& At( TINT a_iIndex ) const
433 {
434 TASSERT( a_iIndex < m_iNumElements );
435 return *( TREINTERPRETCAST( T*, m_poElements ) + a_iIndex );
436 }
437
438 T& operator[]( TINT a_iIndex )
439 {
440 return At( a_iIndex );
441 }
442
443 const T& operator[]( TINT a_iIndex ) const
444 {
445 return At( a_iIndex );
446 }
447
448private:
449 TFORCEINLINE constexpr T& AtUnsafe( TINT a_iIndex )
450 {
451 return *( TREINTERPRETCAST( T*, m_poElements ) + a_iIndex );
452 }
453
454 TFORCEINLINE constexpr const T& AtUnsafe( TINT a_iIndex ) const
455 {
456 return *( TREINTERPRETCAST( T*, m_poElements ) + a_iIndex );
457 }
458
459 void InsertGap( TINT a_iGapAt, TINT a_iGapSize, TINT a_iElementSize, TBOOL a_bUseMemMove = TFALSE )
460 {
461 if ( m_iAllocSize < m_iNumElements + a_iGapSize )
462 {
463 TINT iNewSize = m_iAllocSize + a_iGapSize;
464
465 if ( m_iGrowSize == -1 )
466 iNewSize = TMath::Max( iNewSize, m_iAllocSize * 2 );
467 else
468 iNewSize = TMath::Max( iNewSize, m_iAllocSize + m_iGrowSize );
469
470 TCHAR* pNewBuffer = (TCHAR*)m_pAllocator->Malloc( iNewSize * a_iElementSize );
471
472 if ( m_poElements )
473 {
474 TINT iNumElementsBeforeGap = a_iGapAt;
475 TINT iNumElementsAfterGap = m_iNumElements - a_iGapAt;
476
477 if ( a_bUseMemMove )
478 {
479 // Unsafe way but suitable with simple types
480
481 // Copy elements before the gap
482 if ( iNumElementsBeforeGap > 0 )
483 TUtil::MemCopy( pNewBuffer, m_poElements, iNumElementsBeforeGap * a_iElementSize );
484
485 // Copy elements after the gap
486 if ( iNumElementsAfterGap > 0 )
487 TUtil::MemCopy( pNewBuffer + ( a_iGapAt + a_iGapSize ) * a_iElementSize, TREINTERPRETCAST( TCHAR*, m_poElements ) + a_iGapAt * a_iElementSize, iNumElementsAfterGap * a_iElementSize );
488 }
489 else
490 {
491 // This is much safer
492
493 // Copy elements before the gap
494 for ( TINT i = 0; i < iNumElementsBeforeGap; i++ )
495 {
496 TConstruct<T>( TREINTERPRETCAST( T*, pNewBuffer + ( i * a_iElementSize ) ), std::move( AtUnsafe( i ) ) );
497 AtUnsafe( i ).~T();
498 }
499
500 // Copy elements after the gap
501 for ( TINT i = a_iGapAt + a_iGapSize, k = a_iGapAt; k < m_iNumElements; i++, k++ )
502 {
503 TConstruct<T>( TREINTERPRETCAST( T*, pNewBuffer + ( i * a_iElementSize ) ), std::move( AtUnsafe( k ) ) );
504 AtUnsafe( k ).~T();
505 }
506 }
507
508 // Free the old buffer
509 m_pAllocator->Free( m_poElements );
510 }
511
512 m_poElements = pNewBuffer;
513 m_iAllocSize = iNewSize;
514 m_iNumElements = m_iNumElements + a_iGapSize;
515
516 return;
517 }
518 else if ( m_iNumElements > a_iGapAt )
519 {
520 if ( a_bUseMemMove )
521 {
522 // Unsafe way but suitable with simple types
523 // Note: Seems that in Barnyard there's no other way of adding a gap but in newer Toshi branches there is so I'm adding it here too anyways
524 TUtil::MemMove( &AtUnsafe( a_iGapAt + a_iGapSize ), &AtUnsafe( a_iGapAt ), ( m_iNumElements - a_iGapAt ) * a_iElementSize );
525 }
526 else
527 {
528 // This is much safer
529 for ( TINT i = m_iNumElements - 1, k = i + a_iGapSize; i >= a_iGapAt; i--, k-- )
530 {
531 TConstruct<T>( &AtUnsafe( k ), std::move( AtUnsafe( i ) ) );
532 AtUnsafe( i ).~T();
533 }
534 }
535 }
536
537 m_iNumElements += a_iGapSize;
538 }
539};
540
TFORCEINLINE T * TConstruct(T *a_pMemory, Args &&... args)
Constructs an object in place.
Definition TMemory.h:431
#define TASSERT(X,...)
Definition Defines.h:138
#define TREINTERPRETCAST(TYPE, VALUE)
Definition Defines.h:68
#define TOSHI_API
Definition Defines.h:41
#define TOSHI_NAMESPACE_START
Definition Defines.h:47
#define TFORCEINLINE
Definition Defines.h:74
#define TOSHI_NAMESPACE_END
Definition Defines.h:50
TFORCEINLINE T2Allocator * GetGlobalAllocator()
Definition T2Allocator.h:49
char TCHAR
Definition Typedefs.h:20
#define TNULL
Definition Typedefs.h:23
int TINT
Definition Typedefs.h:7
#define TFALSE
Definition Typedefs.h:24
bool TBOOL
Definition Typedefs.h:6
TFORCEINLINE const T & Max(const T &a, const T &b)
virtual void * Malloc(size_t size, size_t alignment)=0
static void * MemMove(void *dst, const void *src, TSIZE size)
Definition TUtil.h:93
static void * MemCopy(void *dst, const void *src, TSIZE size)
Definition TUtil.h:90
void Grow(TINT a_iNumElements, TINT a_iElementSize)
T2GenericDynamicVector(T2Allocator *a_pAllocator, TINT a_iInitialSize, TINT a_iGrowSize, TINT a_iElementSize)
T2GenericDynamicVector(void *a_poElements, TINT a_iInitialSize, TINT a_iNumElements)
void Reallocate(TINT a_iNewSize, TINT a_iElementSize)
T2DynamicVector(T *a_poElements, TINT a_iInitialSize, TINT a_iNumElements)
TINT Capacity() const
const T & At(TINT a_iIndex) const
const T & operator[](TINT a_iIndex) const
void Erase(const Iterator &a_rIterator)
void FindAndErase(const T &a_rcItem)
Iterator Find(const T &a_rcValue)
void SetSize(TINT a_iNewSize)
void SetSize(TINT a_iNewSize, const T &a_rcValue)
T & At(TINT a_iIndex)
void FindAndEraseFast(const T &a_rcItem)
Iterator InsertAfter(Iterator a_itInsertAfter, const T &a_rcItem=T())
T & operator[](TINT a_iIndex)
T2DynamicVector(T2Allocator *a_pAllocator=GetGlobalAllocator(), TINT a_iInitialSize=0, TINT a_iGrowSize=-1)
TINT Size() const
T * EmplaceBack(Args &&... args)
Iterator MakeIterator(TINT a_iIndex)
void PushBack(const T &item=T())
Iterator InsertBefore(Iterator a_itInsertBefore, const T &a_rcItem=T())
void PushBack(T &&item)
void EraseFast(const Iterator &a_rIterator)
void Reserve(TINT a_iSize)
TBOOL IsEmpty() const
constexpr Iterator & operator=(const Iterator &a_rOther) noexcept
constexpr Iterator(T2DynamicVector *a_pVector)
const T & operator*() const noexcept
TBOOL operator<=(const Iterator &a_rOther) const noexcept
const T * Get() const noexcept
constexpr Iterator(TINT a_iIndex, T2DynamicVector *a_pVector)
constexpr Iterator(const Iterator &a_rOther)
TBOOL operator>=(const Iterator &a_rOther) const noexcept
const T * operator->() const
Iterator operator-(TINT a_iValue) const
constexpr TINT Index() const
constexpr Iterator(T2DynamicVector &a_rVector)
TBOOL operator<(const Iterator &a_rOther) const noexcept
TBOOL operator>(const Iterator &a_rOther) const noexcept
Iterator operator+(TINT a_iValue) const
TBOOL operator==(const Iterator &a_rOther) const noexcept