Files
GTASource/rage/scaleform/Src/GKernel/GArrayUnsafe.h
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

294 lines
9.0 KiB
C++

/**********************************************************************
Filename : GArrayUnsafe.h
Content : Template implementation for GArrayUnsafe
Created : 2008
Authors : MaximShemanarev
Copyright : (c) 2001-2008 Scaleform Corp. All Rights Reserved.
Licensees may use this file in accordance with the valid Scaleform
Commercial License Agreement provided with the software.
This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR ANY PURPOSE.
**********************************************************************/
#ifndef INC_GArrayUnsafe_H
#define INC_GArrayUnsafe_H
#include "GAllocator.h"
// ***** GArrayUnsafeBase
//
// A simple and unsafe modification of the array. It DOES NOT automatically
// resizes the array on PushBack, Append and so on!
//
// Functions Reserve() and Resize() always result in losing all data!
// It's used in performance critical algorithms, such as tessellation,
// where the maximal number of elements is known in advance. There's no
// check for memory overrun, but the address persistence is guaranteed.
// Use with CAUTION!
//
// The code of this class template was taken from the Anti-Grain Geometry
// Project and modified for the use by Scaleform.
// Permission to use without restrictions is hereby granted to
// Scaleform Corp. by the author of Anti-Grain Geometry Project.
//------------------------------------------------------------------------
template<class T, class Allocator> class GArrayUnsafeBase
{
public:
typedef GArrayUnsafeBase<T, Allocator> SelfType;
typedef T ValueType;
typedef Allocator AllocatorType;
~GArrayUnsafeBase()
{
Allocator::DestructArray(Data, Size);
Allocator::Free(Data);
}
GArrayUnsafeBase() : Data(0), Size(0), Capacity(0) {}
GArrayUnsafeBase(UPInt capacity) :
Size(0),
Capacity(capacity),
Data((T*)Allocator::Alloc(this, Capacity * sizeof(T), __FILE__, __LINE__))
{}
GArrayUnsafeBase(const SelfType& v) :
Size(v.Size),
Capacity(v.Capacity),
Data(Capacity ? (T*)Allocator::Alloc(this, Capacity * sizeof(T), __FILE__, __LINE__) : 0)
{
if(Size)
Allocator::CopyArrayForward(Data, v.Data, Size);
}
void Clear()
{
Allocator::DestructArray(Data, Size);
Size = 0;
}
void ClearAndRelease()
{
Allocator::DestructArray(Data, Size);
Allocator::Free(Data);
Size = Capacity = 0;
Data = 0;
}
void CutAt(UPInt newSize)
{
if(newSize < Size)
{
Allocator::DestructArray(Data + newSize, Size - newSize);
Size = newSize;
}
}
// Set new capacity. All data is lost, size is set to zero.
void Reserve(UPInt cap, UPInt extraTail=0)
{
Allocator::DestructArray(Data, Size);
if(cap > Capacity)
{
Allocator::Free(Data);
Capacity = cap + extraTail;
Data = Capacity ? (T*)Allocator::Alloc(this, Capacity * sizeof(T), __FILE__, __LINE__) : 0;
}
Size = 0;
}
UPInt GetCapacity() const
{
return Capacity;
}
UPInt GetNumBytes() const
{
return GetCapacity() * sizeof(ValueType);
}
// Allocate n elements. All data is lost,
// but elements can be accessed in range 0...size-1.
void Resize(UPInt size, UPInt extraTail=0)
{
Reserve(size, extraTail);
Size = size;
Allocator::ConstructArray(Data, size);
}
void Zero()
{
memset(Data, 0, sizeof(T) * Size);
}
void PushBack(const T& v)
{
Allocator::Construct(&Data[Size++], v);
}
template<class S>
void PushBackAlt(const S& val)
{
Allocator::ConstructAlt(&Data[Size++], val);
}
void InsertAt(UPInt pos, const T& val)
{
if(pos >= Size)
{
PushBack(val);
}
else
{
Allocator::Construct(Data + Size);
Allocator::CopyArrayBackward(Data + pos + 1, Data + pos, Size - pos);
Allocator::Construct(Data + pos, val);
++Size;
}
}
#if !RSG_ORBIS // RAGE - doesn't compile, doesn't seem to be used?
// Removing an element from the array is an expensive operation!
// It compacts only after removing the last element.
void RemoveAt(UPInt pos)
{
if (Data.Size == 1)
{
Clear();
}
else
{
Allocator::Destruct(Data + pos);
Allocator::CopyArrayForward(
Data + pos,
Data + pos + 1,
Size - 1 - pos);
--Size;
}
}
#endif // RAGE
UPInt GetSize() const
{
return Size;
}
const SelfType& operator = (const SelfType& v)
{
if(&v != this)
{
Resize(v.Size);
if(Size) Allocator::CopyArrayForward(Data, v.Data, Size);
}
return *this;
}
const T& operator [] (UPInt i) const { return Data[i]; }
T& operator [] (UPInt i) { return Data[i]; }
const T& At(UPInt i) const { return Data[i]; }
T& At(UPInt i) { return Data[i]; }
T ValueAt(UPInt i) const { return Data[i]; }
const T* GetDataPtr() const { return Data; }
T* GetDataPtr() { return Data; }
private:
T* Data;
UPInt Size;
UPInt Capacity;
};
// ***** GArrayUnsafePOD
//
// General purpose "unsafe" array for movable objects that DOES NOT require
// construction/destruction. Constructors and destructors are not called!
// Global heap is in use.
//------------------------------------------------------------------------
template<class T, int SID=GStat_Default_Mem>
class GArrayUnsafePOD :
public GArrayUnsafeBase<T, GAllocatorGH_POD<T, SID> >
{
public:
typedef T ValueType;
typedef GAllocatorGH_POD<T, SID> AllocatorType;
typedef GArrayUnsafeBase<T, AllocatorType> BaseType;
typedef GArrayUnsafePOD<T, SID> SelfType;
GArrayUnsafePOD() : BaseType() {}
GArrayUnsafePOD(UPInt capacity) : BaseType(capacity) {}
GArrayUnsafePOD(const SelfType& v) : BaseType(v) {}
const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
};
// ***** GArrayUnsafe
//
// General purpose "unsafe" array for movable objects that require explicit
// construction/destruction. Global heap is in use.
//------------------------------------------------------------------------
template<class T, int SID=GStat_Default_Mem>
class GArrayUnsafe :
public GArrayUnsafeBase<T, GAllocatorGH<T, SID> >
{
public:
typedef T ValueType;
typedef GAllocatorGH<T, SID> AllocatorType;
typedef GArrayUnsafeBase<T, AllocatorType> BaseType;
typedef GArrayUnsafe<T, SID> SelfType;
GArrayUnsafe() : BaseType() {}
GArrayUnsafe(UPInt capacity) : BaseType(capacity) {}
GArrayUnsafe(const SelfType& v) : BaseType(v) {}
const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
};
// ***** GArrayUnsafeBase
//
// General purpose "unsafe" array for movable objects that DOES NOT require
// construction/destruction. Constructors and destructors are not called!
// Local heap is in use.
//------------------------------------------------------------------------
template<class T, int SID=GStat_Default_Mem>
class GArrayUnsafeLH_POD :
public GArrayUnsafeBase<T, GAllocatorLH_POD<T, SID> >
{
public:
typedef T ValueType;
typedef GAllocatorLH_POD<T, SID> AllocatorType;
typedef GArrayUnsafeBase<T, AllocatorType> BaseType;
typedef GArrayUnsafeLH_POD<T, SID> SelfType;
GArrayUnsafeLH_POD() : BaseType() {}
GArrayUnsafeLH_POD(UPInt capacity) : BaseType(capacity) {}
GArrayUnsafeLH_POD(const SelfType& v) : BaseType(v) {}
const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
};
// ***** GArrayUnsafeLH
//
// General purpose "unsafe" array for movable objects that require explicit
// construction/destruction. Local heap is in use.
//------------------------------------------------------------------------
template<class T, int SID=GStat_Default_Mem>
class GArrayUnsafeLH :
public GArrayUnsafeBase<T, GAllocatorLH<T, SID> >
{
public:
typedef T ValueType;
typedef GAllocatorLH<T, SID> AllocatorType;
typedef GArrayUnsafeBase<T, AllocatorType> BaseType;
typedef GArrayUnsafeLH<T, SID> SelfType;
GArrayUnsafeLH() : BaseType() {}
GArrayUnsafeLH(UPInt capacity) : BaseType(capacity) {}
GArrayUnsafeLH(const SelfType& v) : BaseType(v) {}
const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
};
#endif