📄 untemplate.h
字号:
public:
TIterator( TArray<T>& InArray ) : Array(InArray), Index(-1) { ++*this; }
void operator++() { ++Index; }
INT GetIndex() const { return Index; }
operator UBOOL() const { return Index < Array.Num(); }
T& operator*() const { return Array(Index); }
T* operator->() const { return &Array(Index); }
T& GetCurrent() const { return Array( Index ); }
T& GetPrev() const { return Array( Index ? Index-1 : Array.Num()-1 ); }
T& GetNext() const { return Array( Index<Array.Num()-1 ? Index+1 : 0 ); }
private:
TArray<T>& Array;
INT Index;
};
};
//
// Array operator news.
//
template <class T> void* operator new( size_t Size, TArray<T>& Array )
{
guardSlow(TArray::operator new);
INT Index = Array.Add();
return &Array(Index);
unguardSlow;
}
template <class T> void* operator new( size_t Size, TArray<T>& Array, INT Index )
{
guardSlow(TArray::operator new);
Array.Insert(Index);
return &Array(Index);
unguardSlow;
}
//
// Array exchanger.
//
template <class T> inline void ExchangeArray( TArray<T>& A, TArray<T>& B )
{
guardSlow(ExchangeTArray);
appMemswap( &A, &B, sizeof(FArray) );
unguardSlow;
}
/*-----------------------------------------------------------------------------
Transactional array.
-----------------------------------------------------------------------------*/
template< class T > class TTransArray : public TArray<T>
{
public:
// Constructors.
TTransArray( UObject* InOwner, INT InNum=0 )
: TArray<T>( InNum )
, Owner( InOwner )
{
checkSlow(Owner);
}
TTransArray( UObject* InOwner, const TArray& Other )
: TArray<T>( Other )
, Owner( InOwner )
{
checkSlow(Owner);
}
TTransArray& operator=( const TTransArray& Other )
{
operator=( (const TArray<T>&)Other );
return *this;
}
// Add, Insert, Remove, Empty interface.
INT Add( INT Count=1 )
{
guardSlow(TTransArray::Add);
INT Index = TArray<T>::Add( Count );
if( GUndo )
GUndo->SaveArray( Owner, this, Index, Count, 1, sizeof(T), SerializeItem, DestructItem );
return Index;
unguardSlow;
}
void Insert( INT Index, INT Count=1 )
{
guardSlow(TTransArray::InsertZeroed);
FArray::Insert( Index, Count, sizeof(T) );
if( GUndo )
GUndo->SaveArray( Owner, this, Index, Count, 1, sizeof(T), SerializeItem, DestructItem );
unguardSlow;
}
void Remove( INT Index, INT Count=1 )
{
guardSlow(TTransArray::Remove);
if( GUndo )
GUndo->SaveArray( Owner, this, Index, Count, -1, sizeof(T), SerializeItem, DestructItem );
TArray<T>::Remove( Index, Count );
unguardSlow;
}
void Empty( INT Slack=0 )
{
guardSlow(TTransArray::Empty);
if( GUndo )
GUndo->SaveArray( Owner, this, 0, ArrayNum, -1, sizeof(T), SerializeItem, DestructItem );
TArray<T>::Empty( Slack );
unguardSlow;
}
// Functions dependent on Add, Remove.
TTransArray& operator=( const TArray<T>& Other )
{
guardSlow(TTransArray::operator=);
if( this != &Other )
{
Empty( Other.Num() );
for( INT i=0; i<Other.Num(); i++ )
new( *this )T( Other(i) );
}
return *this;
unguardSlow;
}
INT AddItem( const T& Item )
{
guardSlow(TTransArray::AddItem);
INT Index=Add();
(*this)(Index)=Item;
return Index;
unguardSlow;
}
INT AddZeroed( INT n=1 )
{
guardSlow(TTransArray::AddZeroed);
INT Index = Add(n);
appMemzero( &(*this)(Index), n*sizeof(T) );
return Index;
unguardSlow;
}
INT AddUniqueItem( const T& Item )
{
guardSlow(TTransArray::AddUniqueItem);
for( INT Index=0; Index<ArrayNum; Index++ )
if( (*this)(Index)==Item )
return Index;
return AddItem( Item );
unguardSlow;
}
INT RemoveItem( const T& Item )
{
guardSlow(TTransArray::RemoveItem);
INT OriginalNum=ArrayNum;
for( INT Index=0; Index<ArrayNum; Index++ )
if( (*this)(Index)==Item )
Remove( Index-- );
return OriginalNum - ArrayNum;
unguardSlow;
}
// TTransArray interface.
UObject* GetOwner()
{
return Owner;
}
void ModifyItem( INT Index )
{
guardSlow(TTransArray::ModifyItem);
if( GUndo )
GUndo->SaveArray( Owner, this, Index, 1, 0, sizeof(T), SerializeItem, DestructItem );
unguardSlow;
}
void ModifyAllItems()
{
guardSlow(TTransArray::ModifyAllItems);
if( GUndo )
GUndo->SaveArray( Owner, this, 0, Num(), 0, sizeof(T), SerializeItem, DestructItem );
unguardSlow;
}
friend FArchive& operator<<( FArchive& Ar, TTransArray& A )
{
guard(TTransArray<<);
if( !Ar.IsTrans() )
Ar << (TArray<T>&)A;
return Ar;
unguard;
}
protected:
static void SerializeItem( FArchive& Ar, void* TPtr )
{
guardSlow(TArray::SerializeItem);
Ar << *(T*)TPtr;
unguardSlow;
}
static void DestructItem( void* TPtr )
{
guardSlow(TArray::SerializeItem);
((T*)TPtr)->~T();
unguardSlow;
}
UObject* Owner;
private:
// Disallow the copy constructor.
TTransArray( const TArray& Other )
{}
};
//
// Transactional array operator news.
//
template <class T> void* operator new( size_t Size, TTransArray<T>& Array )
{
guardSlow(TArray::operator new);
INT Index = Array.Add();
return &Array(Index);
unguardSlow;
}
template <class T> void* operator new( size_t Size, TTransArray<T>& Array, INT Index )
{
guardSlow(TArray::operator new);
Array.Insert(Index);
return &Array(Index);
unguardSlow;
}
/*-----------------------------------------------------------------------------
Lazy loading.
-----------------------------------------------------------------------------*/
//
// Lazy loader base class.
//
class FLazyLoader
{
friend class ULinkerLoad;
protected:
FArchive* SavedAr;
INT SavedPos;
public:
FLazyLoader()
: SavedAr( NULL )
, SavedPos( 0 )
{}
virtual void Load()=0;
virtual void Unload()=0;
};
//
// Lazy-loadable dynamic array.
//
template <class T> class TLazyArray : public TArray<T>, public FLazyLoader
{
public:
TLazyArray( INT InNum=0 )
: TArray<T>( InNum )
, FLazyLoader()
{}
~TLazyArray()
{
guard(TLazyArray::~TLazyArray);
if( SavedAr )
SavedAr->DetachLazyLoader( this );
unguard;
}
#if LOAD_ON_DEMAND /* Breaks because of untimely accesses of operator() !! */
T& operator()( INT i )
{
guardSlow(TArray::operator());
checkSlow(i>=0);
checkSlow(i<=ArrayNum);
checkSlow(ArrayMax>=ArrayNum);
if( SavedPos>0 )
Load();
return ((T*)Data)[i];
unguardSlow;
}
const T& operator()( INT i ) const
{
guardSlow(TArray::operator());
checkSlow(i>=0);
checkSlow(i<=ArrayNum);
checkSlow(ArrayMax>=ArrayNum);
if( SavedPos>0 )
Load();
return ((T*)Data)[i];
unguardSlow;
}
#endif
void Load()
{
// Make sure this array is loaded.
guard(TLazyArray::Load);
if( SavedPos>0 )
{
// Lazy load it now.
INT PushedPos = SavedAr->Tell();
SavedAr->Seek( SavedPos );
*SavedAr << (TArray<T>&)*this;
SavedPos *= -1;
SavedAr->Seek( PushedPos );
}
unguard;
}
void Unload()
{
// Make sure this array is unloaded.
guard(TLazyArray::Unload);
if( SavedPos<0 )
{
// Unload it now.
Empty();
SavedPos *= -1;
}
unguard;
}
friend FArchive& operator<<( FArchive& Ar, TLazyArray& This )
{
guard(TLazyArray<<);
if( Ar.IsLoading() )
{
INT SeekPos=0;
if( Ar.Ver() <= 61 )
{
//oldver: Handles dynamic arrays of fixed-length serialized items only.
Ar.AttachLazyLoader( &This );
INT SkipCount;
Ar << AR_INDEX(SkipCount);
SeekPos = Ar.Tell() + SkipCount*sizeof(T);
}
else
{
Ar << SeekPos;
Ar.AttachLazyLoader( &This );
}
if( !GLazyLoad )
This.Load();
Ar.Seek( SeekPos );
}
else if( Ar.IsSaving() && Ar.Ver()>61 )
{
// Save out count for skipping over this data.
INT CountPos = Ar.Tell();
Ar << CountPos << (TArray<T>&)This;
INT EndPos = Ar.Tell();
Ar.Seek( CountPos );
Ar << EndPos;
Ar.Seek( EndPos );
}
else Ar << (TArray<T>&)This;
return Ar;
unguard;
}
};
/*-----------------------------------------------------------------------------
Dynamic strings.
-----------------------------------------------------------------------------*/
//
// A dynamically sizeable string.
//
class CORE_API FString : protected TArray<TCHAR>
{
public:
FString()
: TArray<TCHAR>()
{}
FString( const TCHAR* In )
: TArray<TCHAR>( *In ? (appStrlen(In)+1) : 0 )
{
if( ArrayNum )
appMemcpy( &(*this)(0), In, ArrayNum*sizeof(TCHAR) );
}
FString( const FString& Other )
: TArray<TCHAR>( Other.ArrayNum )
{
if( ArrayNum )
appMemcpy( &(*this)(0), &Other(0), ArrayNum*sizeof(TCHAR) );
}
FString( ENoInit )
: TArray<TCHAR>( E_NoInit )
{}
explicit FString( BYTE Arg, INT Digits=1 );
explicit FString( SBYTE Arg, INT Digits=1 );
explicit FString( _WORD Arg, INT Digits=1 );
explicit FString( SWORD Arg, INT Digits=1 );
explicit FString( INT Arg, INT Digits=1 );
explicit FString( DWORD Arg, INT Digits=1 );
explicit FString( FLOAT Arg, INT Digits=1, INT RightDigits=0, UBOOL LeadZero=1 );
explicit FString( DOUBLE Arg, INT Digits=1, INT RightDigits=0, UBOOL LeadZero=1 );
FString& operator=( const TCHAR* Other )
{
if( &(*this)(0)!=Other )
{
ArrayNum = ArrayMax = *Other ? appStrlen(Other)+1 : 0;
Realloc( sizeof(TCHAR) );
if( ArrayNum )
appMemcpy( &(*this)(0), Other, ArrayNum*sizeof(TCHAR) );
}
return *this;
}
FString& operator=( const FString& Other )
{
if( this != &Other )
{
ArrayNum = ArrayMax = Other.Num();
Realloc( sizeof(TCHAR) );
if( ArrayNum )
appMemcpy( &(*this)(0), *Other, ArrayNum*sizeof(TCHAR) );
}
return *this;
}
~FString()
{
TArray<TCHAR>::Empty();
}
void Empty()
{
TArray<TCHAR>::Empty();
}
void Shrink()
{
TArray<TCHAR>::Shrink();
}
const TCHAR* operator*() const
{
return Num() ? &(*this)(0) : TEXT("");
}
operator UBOOL() const
{
return Num()!=0;
}
TArray<TCHAR>& GetCharArray()
{
//warning: Operations on the TArray<CHAR> can be unsafe, such as adding
// non-terminating 0's or removing the terminating zero.
return (TArray<TCHAR>&)*this;
}
FString& operator+=( const TCHAR* Str )
{
if( ArrayNum )
{
INT Index = ArrayNum-1;
Add( appStrlen(Str) );
appStrcpy( &(*this)(Index), Str );
}
else if( *Str )
{
Add( appStrlen(Str)+1 );
appStrcpy( &(*this)(0), Str );
}
return *this;
}
FString& operator+=( const FString& Str )
{
return operator+=( *Str );
}
FString operator+( const TCHAR* Str )
{
return FString( *this ) += Str;
}
FString operator+( const FString& Str )
{
return operator+( *Str );
}
FString& operator*=( const TCHAR* Str )
{
if( ArrayNum>1 && (*this)(ArrayNum-2)!=PATH_SEPARATOR[0] )
*this += PATH_SEPARATOR;
return *this += Str;
}
FString& operator*=( const FString& Str )
{
return operator*=( *Str );
}
FString operator*( const TCHAR* Str ) const
{
return FString( *this ) *= Str;
}
FString operator*( const FString& Str ) const
{
return operator*( *Str );
}
UBOOL operator==( const TCHAR* Other ) const
{
return appStricmp( **this, Other )==0;
}
UBOOL operator==( const FString& Other ) const
{
return appStricmp( **this, *Other )==0;
}
UBOOL operator!=( const TCHAR* Other ) const
{
return appStricmp( **this, Other )!=0;
}
UBOOL operator!=( const FString& Other ) const
{
return appStricmp( **this, *Other )!=0;
}
INT Len() const
{
return Num() ? Num()-1 : 0;
}
FString Left( INT Count ) const
{
return FString( Clamp(Count,0,Len()), **this );
}
FString LeftChop( INT Count ) const
{
return FString( Clamp(Len()-Count,0,Len()), **this );
}
FString Right( INT Count ) const
{
return FString( **this + Len()-Clamp(Count,0,Len()) );
}
FString Mid( INT Start, INT Count=MAXINT ) const
{
DWORD End = Start+Count;
Start = Clamp( (DWORD)Start, (DWORD)0, (DWORD)Len() );
End = Clamp( (DWORD)End, (DWORD)Start, (DWORD)Len() );
return FString( End-Start, **this + Start );
}
INT InStr( const TCHAR* SubStr ) const
{
TCHAR* Tmp = appStrstr(**this,SubStr);
return Tmp ? (Tmp-**this) : -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -