Files
ReshadePluginsCore/JediSurvivor/UnrealContainers.hpp

910 lines
27 KiB
C++
Raw Normal View History

2025-12-03 14:06:04 +01:00
#pragma once
/*
* SDK generated by Dumper-7
*
* https://github.com/Encryqed/Dumper-7
*/
// Container implementations with iterators. See https://github.com/Fischsalat/UnrealContainers
#include <string>
#include <stdexcept>
#include <iostream>
#include "UtfN.hpp"
namespace UC
{
typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
template<typename ArrayElementType>
class TArray;
template<typename SparseArrayElementType>
class TSparseArray;
template<typename SetElementType>
class TSet;
template<typename KeyElementType, typename ValueElementType>
class TMap;
template<typename KeyElementType, typename ValueElementType>
class TPair;
namespace Iterators
{
class FSetBitIterator;
template<typename ArrayType>
class TArrayIterator;
template<class ContainerType>
class TContainerIterator;
template<typename SparseArrayElementType>
using TSparseArrayIterator = TContainerIterator<TSparseArray<SparseArrayElementType>>;
template<typename SetElementType>
using TSetIterator = TContainerIterator<TSet<SetElementType>>;
template<typename KeyElementType, typename ValueElementType>
using TMapIterator = TContainerIterator<TMap<KeyElementType, ValueElementType>>;
}
namespace ContainerImpl
{
namespace HelperFunctions
{
inline uint32 FloorLog2(uint32 Value)
{
uint32 pos = 0;
if (Value >= 1 << 16) { Value >>= 16; pos += 16; }
if (Value >= 1 << 8) { Value >>= 8; pos += 8; }
if (Value >= 1 << 4) { Value >>= 4; pos += 4; }
if (Value >= 1 << 2) { Value >>= 2; pos += 2; }
if (Value >= 1 << 1) { pos += 1; }
return pos;
}
inline uint32 CountLeadingZeros(uint32 Value)
{
if (Value == 0)
return 32;
return 31 - FloorLog2(Value);
}
}
template<int32 Size, uint32 Alignment>
struct TAlignedBytes
{
alignas(Alignment) uint8 Pad[Size];
};
template<uint32 NumInlineElements>
class TInlineAllocator
{
public:
template<typename ElementType>
class ForElementType
{
private:
static constexpr int32 ElementSize = sizeof(ElementType);
static constexpr int32 ElementAlign = alignof(ElementType);
static constexpr int32 InlineDataSizeBytes = NumInlineElements * ElementSize;
private:
TAlignedBytes<ElementSize, ElementAlign> InlineData[NumInlineElements];
ElementType* SecondaryData;
public:
ForElementType()
: InlineData{ 0x0 }, SecondaryData(nullptr)
{
}
ForElementType(ForElementType&&) = default;
ForElementType(const ForElementType&) = default;
public:
ForElementType& operator=(ForElementType&&) = default;
ForElementType& operator=(const ForElementType&) = default;
public:
inline const ElementType* GetAllocation() const { return SecondaryData ? SecondaryData : reinterpret_cast<const ElementType*>(&InlineData); }
inline uint32 GetNumInlineBytes() const { return NumInlineElements; }
};
};
class FBitArray
{
protected:
static constexpr int32 NumBitsPerDWORD = 32;
static constexpr int32 NumBitsPerDWORDLogTwo = 5;
private:
TInlineAllocator<4>::ForElementType<int32> Data;
int32 NumBits;
int32 MaxBits;
public:
FBitArray()
: NumBits(0), MaxBits(Data.GetNumInlineBytes() * NumBitsPerDWORD)
{
}
FBitArray(const FBitArray&) = default;
FBitArray(FBitArray&&) = default;
public:
FBitArray& operator=(FBitArray&&) = default;
FBitArray& operator=(const FBitArray& Other) = default;
private:
inline void VerifyIndex(int32 Index) const { if (!IsValidIndex(Index)) throw std::out_of_range("Index was out of range!"); }
public:
inline int32 Num() const { return NumBits; }
inline int32 Max() const { return MaxBits; }
inline const uint32* GetData() const { return reinterpret_cast<const uint32*>(Data.GetAllocation()); }
inline bool IsValidIndex(int32 Index) const { return Index >= 0 && Index < NumBits; }
inline bool IsValid() const { return GetData() && NumBits > 0; }
public:
inline bool operator[](int32 Index) const { VerifyIndex(Index); return GetData()[Index / NumBitsPerDWORD] & (1 << (Index & (NumBitsPerDWORD - 1))); }
inline bool operator==(const FBitArray& Other) const { return NumBits == Other.NumBits && GetData() == Other.GetData(); }
inline bool operator!=(const FBitArray& Other) const { return NumBits != Other.NumBits || GetData() != Other.GetData(); }
public:
friend Iterators::FSetBitIterator begin(const FBitArray& Array);
friend Iterators::FSetBitIterator end (const FBitArray& Array);
};
template<typename SparseArrayType>
union TSparseArrayElementOrFreeListLink
{
SparseArrayType ElementData;
struct
{
int32 PrevFreeIndex;
int32 NextFreeIndex;
};
};
template<typename SetType>
class SetElement
{
private:
template<typename SetDataType>
friend class TSet;
private:
SetType Value;
int32 HashNextId;
int32 HashIndex;
};
}
template <typename KeyType, typename ValueType>
class TPair
{
public:
KeyType First;
ValueType Second;
public:
TPair(KeyType Key, ValueType Value)
: First(Key), Second(Value)
{
}
public:
inline KeyType& Key() { return First; }
inline const KeyType& Key() const { return First; }
inline ValueType& Value() { return Second; }
inline const ValueType& Value() const { return Second; }
};
template<typename ArrayElementType>
class TArray
{
private:
template<typename ArrayElementType>
friend class TAllocatedArray;
template<typename SparseArrayElementType>
friend class TSparseArray;
protected:
static constexpr uint64 ElementAlign = alignof(ArrayElementType);
static constexpr uint64 ElementSize = sizeof(ArrayElementType);
protected:
ArrayElementType* Data;
int32 NumElements;
int32 MaxElements;
public:
TArray()
: TArray(nullptr, 0, 0)
{
}
TArray(ArrayElementType* Data, int32 NumElements, int32 MaxElements)
: Data(Data), NumElements(NumElements), MaxElements(MaxElements)
{
}
TArray(const TArray&) = default;
TArray(TArray&&) = default;
public:
TArray& operator=(TArray&&) = default;
TArray& operator=(const TArray&) = default;
private:
inline int32 GetSlack() const { return MaxElements - NumElements; }
inline void VerifyIndex(int32 Index) const { if (!IsValidIndex(Index)) throw std::out_of_range("Index was out of range!"); }
inline ArrayElementType& GetUnsafe(int32 Index) { return Data[Index]; }
inline const ArrayElementType& GetUnsafe(int32 Index) const { return Data[Index]; }
public:
/* Adds to the array if there is still space for one more element */
inline bool Add(const ArrayElementType& Element)
{
if (GetSlack() <= 0)
return false;
Data[NumElements] = Element;
NumElements++;
return true;
}
inline bool Remove(int32 Index)
{
if (!IsValidIndex(Index))
return false;
NumElements--;
for (int i = Index; i < NumElements; i++)
{
/* NumElements was decremented, acessing i + 1 is safe */
Data[i] = Data[i + 1];
}
return true;
}
inline void Clear()
{
NumElements = 0;
if (Data)
memset(Data, 0, NumElements * ElementSize);
}
public:
inline int32 Num() const { return NumElements; }
inline int32 Max() const { return MaxElements; }
inline const ArrayElementType* GetDataPtr() const { return Data; }
inline bool IsValidIndex(int32 Index) const { return Data && Index >= 0 && Index < NumElements; }
inline bool IsValid() const { return Data && NumElements > 0 && MaxElements >= NumElements; }
public:
inline ArrayElementType& operator[](int32 Index) { VerifyIndex(Index); return Data[Index]; }
inline const ArrayElementType& operator[](int32 Index) const { VerifyIndex(Index); return Data[Index]; }
inline bool operator==(const TArray<ArrayElementType>& Other) const { return Data == Other.Data; }
inline bool operator!=(const TArray<ArrayElementType>& Other) const { return Data != Other.Data; }
inline explicit operator bool() const { return IsValid(); };
public:
template<typename T> friend Iterators::TArrayIterator<T> begin(const TArray& Array);
template<typename T> friend Iterators::TArrayIterator<T> end (const TArray& Array);
};
class FString : public TArray<wchar_t>
{
public:
friend std::ostream& operator<<(std::ostream& Stream, const UC::FString& Str) { return Stream << Str.ToString(); }
public:
using TArray::TArray;
FString(const wchar_t* Str)
{
const uint32 NullTerminatedLength = static_cast<uint32>(wcslen(Str) + 0x1);
Data = const_cast<wchar_t*>(Str);
NumElements = NullTerminatedLength;
MaxElements = NullTerminatedLength;
}
FString(wchar_t* Str, int32 Num, int32 Max)
{
Data = Str;
NumElements = Num;
MaxElements = Max;
}
public:
inline std::string ToString() const
{
if (*this)
{
return UtfN::Utf16StringToUtf8String<std::string>(Data, NumElements - 1); // Exclude null-terminator
}
return "";
}
inline std::wstring ToWString() const
{
if (*this)
return std::wstring(Data);
return L"";
}
public:
inline wchar_t* CStr() { return Data; }
inline const wchar_t* CStr() const { return Data; }
public:
inline bool operator==(const FString& Other) const { return Other ? NumElements == Other.NumElements && wcscmp(Data, Other.Data) == 0 : false; }
inline bool operator!=(const FString& Other) const { return Other ? NumElements != Other.NumElements || wcscmp(Data, Other.Data) != 0 : true; }
};
// Utf8String that assumes C-APIs (strlen, strcmp) behaviour works for char8_t like Ansi strings, execept it's counting/comparing bytes not characters.
class FUtf8String : public TArray<char8_t>
{
public:
friend std::ostream& operator<<(std::ostream& Stream, const UC::FUtf8String& Str) { return Stream << Str.ToString(); }
private:
inline const char* GetDataAsConstCharPtr() const
{
return reinterpret_cast<const char*>(Data);
}
public:
using TArray::TArray;
FUtf8String(const char8_t* Str)
{
Data = const_cast<char8_t*>(Str);
const uint32 NullTerminatedLength = static_cast<uint32>(strlen(GetDataAsConstCharPtr()) + 0x1);
NumElements = NullTerminatedLength;
MaxElements = NullTerminatedLength;
}
FUtf8String(char8_t* Str, int32 Num, int32 Max)
{
Data = Str;
NumElements = Num;
MaxElements = Max;
}
public:
inline std::string ToString() const
{
if (*this)
{
return std::string(GetDataAsConstCharPtr(), NumElements - 1); // Exclude null-terminator
}
return "";
}
inline std::wstring ToWString() const
{
if (*this)
return UtfN::StringToWString<std::string>(ToString()); // Exclude null-terminator
return L"";
}
public:
inline char8_t* CStr() { return Data; }
inline const char8_t* CStr() const { return Data; }
public:
inline bool operator==(const FUtf8String& Other) const { return Other ? NumElements == Other.NumElements && strcmp(GetDataAsConstCharPtr(), Other.GetDataAsConstCharPtr()) == 0 : false; }
inline bool operator!=(const FUtf8String& Other) const { return Other ? NumElements != Other.NumElements || strcmp(GetDataAsConstCharPtr(), Other.GetDataAsConstCharPtr()) != 0 : true; }
};
class FAnsiString : public TArray<char>
{
public:
friend std::ostream& operator<<(std::ostream& Stream, const UC::FAnsiString& Str) { return Stream << Str.ToString(); }
public:
using TArray::TArray;
FAnsiString(const char* Str)
{
const uint32 NullTerminatedLength = static_cast<uint32>(strlen(Str) + 0x1);
Data = const_cast<char*>(Str);
NumElements = NullTerminatedLength;
MaxElements = NullTerminatedLength;
}
FAnsiString(char* Str, int32 Num, int32 Max)
{
Data = Str;
NumElements = Num;
MaxElements = Max;
}
public:
inline std::string ToString() const
{
if (*this)
{
return std::string(Data, NumElements - 1); // Exclude null-terminator
}
return "";
}
inline std::wstring ToWString() const
{
if (*this)
return UtfN::StringToWString<std::string>(ToString()); // Exclude null-terminator
return L"";
}
public:
inline char* CStr() { return Data; }
inline const char* CStr() const { return Data; }
public:
inline bool operator==(const FAnsiString& Other) const { return Other ? NumElements == Other.NumElements && strcmp(Data, Other.Data) == 0 : false; }
inline bool operator!=(const FAnsiString& Other) const { return Other ? NumElements != Other.NumElements || strcmp(Data, Other.Data) != 0 : true; }
};
/*
* Class to allow construction of a TArray, that uses c-style standard-library memory allocation.
*
* Useful for calling functions that expect a buffer of a certain size and do not reallocate that buffer.
* This avoids leaking memory, if the array would otherwise be allocated by the engine, and couldn't be freed without FMemory-functions.
*/
template<typename ArrayElementType>
class TAllocatedArray : public TArray<ArrayElementType>
{
public:
TAllocatedArray() = delete;
public:
TAllocatedArray(int32 Size)
{
this->Data = static_cast<ArrayElementType*>(malloc(Size * sizeof(ArrayElementType)));
this->NumElements = 0x0;
this->MaxElements = Size;
}
~TAllocatedArray()
{
if (this->Data)
free(this->Data);
this->NumElements = 0x0;
this->MaxElements = 0x0;
}
public:
inline operator TArray<ArrayElementType>() { return *reinterpret_cast< TArray<ArrayElementType>*>(this); }
inline operator const TArray<ArrayElementType>() const { return *reinterpret_cast<const TArray<ArrayElementType>*>(this); }
};
/*
* Class to allow construction of an FString, that uses c-style standard-library memory allocation.
*
* Useful for calling functions that expect a buffer of a certain size and do not reallocate that buffer.
* This avoids leaking memory, if the array would otherwise be allocated by the engine, and couldn't be freed without FMemory-functions.
*/
class FAllocatedString : public FString
{
public:
FAllocatedString() = delete;
public:
FAllocatedString(int32 Size)
{
Data = static_cast<wchar_t*>(malloc(Size * sizeof(wchar_t)));
NumElements = 0x0;
MaxElements = Size;
}
~FAllocatedString()
{
if (Data)
free(Data);
NumElements = 0x0;
MaxElements = 0x0;
}
public:
inline operator FString() { return *reinterpret_cast< FString*>(this); }
inline operator const FString() const { return *reinterpret_cast<const FString*>(this); }
};
template<typename SparseArrayElementType>
class TSparseArray
{
private:
static constexpr uint32 ElementAlign = alignof(SparseArrayElementType);
static constexpr uint32 ElementSize = sizeof(SparseArrayElementType);
private:
using FElementOrFreeListLink = ContainerImpl::TSparseArrayElementOrFreeListLink<ContainerImpl::TAlignedBytes<ElementSize, ElementAlign>>;
private:
TArray<FElementOrFreeListLink> Data;
ContainerImpl::FBitArray AllocationFlags;
int32 FirstFreeIndex;
int32 NumFreeIndices;
public:
TSparseArray()
: FirstFreeIndex(-1), NumFreeIndices(0)
{
}
TSparseArray(TSparseArray&&) = default;
TSparseArray(const TSparseArray&) = default;
public:
TSparseArray& operator=(TSparseArray&&) = default;
TSparseArray& operator=(const TSparseArray&) = default;
private:
inline void VerifyIndex(int32 Index) const { if (!IsValidIndex(Index)) throw std::out_of_range("Index was out of range!"); }
public:
inline int32 NumAllocated() const { return Data.Num(); }
inline int32 Num() const { return NumAllocated() - NumFreeIndices; }
inline int32 Max() const { return Data.Max(); }
inline bool IsValidIndex(int32 Index) const { return Data.IsValidIndex(Index) && AllocationFlags[Index]; }
inline bool IsValid() const { return Data.IsValid() && AllocationFlags.IsValid(); }
public:
const ContainerImpl::FBitArray& GetAllocationFlags() const { return AllocationFlags; }
public:
inline SparseArrayElementType& operator[](int32 Index) { VerifyIndex(Index); return *reinterpret_cast<SparseArrayElementType*>(&Data.GetUnsafe(Index).ElementData); }
inline const SparseArrayElementType& operator[](int32 Index) const { VerifyIndex(Index); return *reinterpret_cast<SparseArrayElementType*>(&Data.GetUnsafe(Index).ElementData); }
inline bool operator==(const TSparseArray<SparseArrayElementType>& Other) const { return Data == Other.Data; }
inline bool operator!=(const TSparseArray<SparseArrayElementType>& Other) const { return Data != Other.Data; }
public:
template<typename T> friend Iterators::TSparseArrayIterator<T> begin(const TSparseArray& Array);
template<typename T> friend Iterators::TSparseArrayIterator<T> end (const TSparseArray& Array);
};
template<typename SetElementType>
class TSet
{
private:
static constexpr uint32 ElementAlign = alignof(SetElementType);
static constexpr uint32 ElementSize = sizeof(SetElementType);
private:
using SetDataType = ContainerImpl::SetElement<SetElementType>;
using HashType = ContainerImpl::TInlineAllocator<1>::ForElementType<int32>;
private:
TSparseArray<SetDataType> Elements;
HashType Hash;
int32 HashSize;
public:
TSet()
: HashSize(0)
{
}
TSet(TSet&&) = default;
TSet(const TSet&) = default;
public:
TSet& operator=(TSet&&) = default;
TSet& operator=(const TSet&) = default;
private:
inline void VerifyIndex(int32 Index) const { if (!IsValidIndex(Index)) throw std::out_of_range("Index was out of range!"); }
public:
inline int32 NumAllocated() const { return Elements.NumAllocated(); }
inline int32 Num() const { return Elements.Num(); }
inline int32 Max() const { return Elements.Max(); }
inline bool IsValidIndex(int32 Index) const { return Elements.IsValidIndex(Index); }
inline bool IsValid() const { return Elements.IsValid(); }
public:
const ContainerImpl::FBitArray& GetAllocationFlags() const { return Elements.GetAllocationFlags(); }
public:
inline SetElementType& operator[] (int32 Index) { return Elements[Index].Value; }
inline const SetElementType& operator[] (int32 Index) const { return Elements[Index].Value; }
inline bool operator==(const TSet<SetElementType>& Other) const { return Elements == Other.Elements; }
inline bool operator!=(const TSet<SetElementType>& Other) const { return Elements != Other.Elements; }
public:
template<typename T> friend Iterators::TSetIterator<T> begin(const TSet& Set);
template<typename T> friend Iterators::TSetIterator<T> end (const TSet& Set);
};
template<typename KeyElementType, typename ValueElementType>
class TMap
{
public:
using ElementType = TPair<KeyElementType, ValueElementType>;
private:
TSet<ElementType> Elements;
private:
inline void VerifyIndex(int32 Index) const { if (!IsValidIndex(Index)) throw std::out_of_range("Index was out of range!"); }
public:
inline int32 NumAllocated() const { return Elements.NumAllocated(); }
inline int32 Num() const { return Elements.Num(); }
inline int32 Max() const { return Elements.Max(); }
inline bool IsValidIndex(int32 Index) const { return Elements.IsValidIndex(Index); }
inline bool IsValid() const { return Elements.IsValid(); }
public:
const ContainerImpl::FBitArray& GetAllocationFlags() const { return Elements.GetAllocationFlags(); }
public:
inline decltype(auto) Find(const KeyElementType& Key, bool(*Equals)(const KeyElementType& LeftKey, const KeyElementType& RightKey))
{
for (auto It = begin(*this); It != end(*this); ++It)
{
if (Equals(It->Key(), Key))
return It;
}
return end(*this);
}
public:
inline ElementType& operator[] (int32 Index) { return Elements[Index]; }
inline const ElementType& operator[] (int32 Index) const { return Elements[Index]; }
inline bool operator==(const TMap<KeyElementType, ValueElementType>& Other) const { return Elements == Other.Elements; }
inline bool operator!=(const TMap<KeyElementType, ValueElementType>& Other) const { return Elements != Other.Elements; }
public:
template<typename KeyType, typename ValueType> friend Iterators::TMapIterator<KeyType, ValueType> begin(const TMap& Map);
template<typename KeyType, typename ValueType> friend Iterators::TMapIterator<KeyType, ValueType> end (const TMap& Map);
};
namespace Iterators
{
class FRelativeBitReference
{
protected:
static constexpr int32 NumBitsPerDWORD = 32;
static constexpr int32 NumBitsPerDWORDLogTwo = 5;
public:
inline explicit FRelativeBitReference(int32 BitIndex)
: WordIndex(BitIndex >> NumBitsPerDWORDLogTwo)
, Mask(1 << (BitIndex & (NumBitsPerDWORD - 1)))
{
}
int32 WordIndex;
uint32 Mask;
};
class FSetBitIterator : public FRelativeBitReference
{
private:
const ContainerImpl::FBitArray& Array;
uint32 UnvisitedBitMask;
int32 CurrentBitIndex;
int32 BaseBitIndex;
public:
explicit FSetBitIterator(const ContainerImpl::FBitArray& InArray, int32 StartIndex = 0)
: FRelativeBitReference(StartIndex)
, Array(InArray)
, UnvisitedBitMask((~0U) << (StartIndex & (NumBitsPerDWORD - 1)))
, CurrentBitIndex(StartIndex)
, BaseBitIndex(StartIndex & ~(NumBitsPerDWORD - 1))
{
if (StartIndex != Array.Num())
FindFirstSetBit();
}
public:
inline FSetBitIterator& operator++()
{
UnvisitedBitMask &= ~this->Mask;
FindFirstSetBit();
return *this;
}
inline explicit operator bool() const { return CurrentBitIndex < Array.Num(); }
inline bool operator==(const FSetBitIterator& Rhs) const { return CurrentBitIndex == Rhs.CurrentBitIndex && &Array == &Rhs.Array; }
inline bool operator!=(const FSetBitIterator& Rhs) const { return CurrentBitIndex != Rhs.CurrentBitIndex || &Array != &Rhs.Array; }
public:
inline int32 GetIndex() { return CurrentBitIndex; }
void FindFirstSetBit()
{
const uint32* ArrayData = Array.GetData();
const int32 ArrayNum = Array.Num();
const int32 LastWordIndex = (ArrayNum - 1) / NumBitsPerDWORD;
uint32 RemainingBitMask = ArrayData[this->WordIndex] & UnvisitedBitMask;
while (!RemainingBitMask)
{
++this->WordIndex;
BaseBitIndex += NumBitsPerDWORD;
if (this->WordIndex > LastWordIndex)
{
CurrentBitIndex = ArrayNum;
return;
}
RemainingBitMask = ArrayData[this->WordIndex];
UnvisitedBitMask = ~0;
}
const uint32 NewRemainingBitMask = RemainingBitMask & (RemainingBitMask - 1);
this->Mask = NewRemainingBitMask ^ RemainingBitMask;
CurrentBitIndex = BaseBitIndex + NumBitsPerDWORD - 1 - ContainerImpl::HelperFunctions::CountLeadingZeros(this->Mask);
if (CurrentBitIndex > ArrayNum)
CurrentBitIndex = ArrayNum;
}
};
template<typename ArrayType>
class TArrayIterator
{
private:
TArray<ArrayType>& IteratedArray;
int32 Index;
public:
TArrayIterator(const TArray<ArrayType>& Array, int32 StartIndex = 0x0)
: IteratedArray(const_cast<TArray<ArrayType>&>(Array)), Index(StartIndex)
{
}
public:
inline int32 GetIndex() { return Index; }
inline int32 IsValid() { return IteratedArray.IsValidIndex(GetIndex()); }
public:
inline TArrayIterator& operator++() { ++Index; return *this; }
inline TArrayIterator& operator--() { --Index; return *this; }
inline ArrayType& operator*() { return IteratedArray[GetIndex()]; }
inline const ArrayType& operator*() const { return IteratedArray[GetIndex()]; }
inline ArrayType* operator->() { return &IteratedArray[GetIndex()]; }
inline const ArrayType* operator->() const { return &IteratedArray[GetIndex()]; }
inline bool operator==(const TArrayIterator& Other) const { return &IteratedArray == &Other.IteratedArray && Index == Other.Index; }
inline bool operator!=(const TArrayIterator& Other) const { return &IteratedArray != &Other.IteratedArray || Index != Other.Index; }
};
template<class ContainerType>
class TContainerIterator
{
private:
ContainerType& IteratedContainer;
FSetBitIterator BitIterator;
public:
TContainerIterator(const ContainerType& Container, const ContainerImpl::FBitArray& BitArray, int32 StartIndex = 0x0)
: IteratedContainer(const_cast<ContainerType&>(Container)), BitIterator(BitArray, StartIndex)
{
}
public:
inline int32 GetIndex() { return BitIterator.GetIndex(); }
inline int32 IsValid() { return IteratedContainer.IsValidIndex(GetIndex()); }
public:
inline TContainerIterator& operator++() { ++BitIterator; return *this; }
inline TContainerIterator& operator--() { --BitIterator; return *this; }
inline auto& operator*() { return IteratedContainer[GetIndex()]; }
inline const auto& operator*() const { return IteratedContainer[GetIndex()]; }
inline auto* operator->() { return &IteratedContainer[GetIndex()]; }
inline const auto* operator->() const { return &IteratedContainer[GetIndex()]; }
inline bool operator==(const TContainerIterator& Other) const { return &IteratedContainer == &Other.IteratedContainer && BitIterator == Other.BitIterator; }
inline bool operator!=(const TContainerIterator& Other) const { return &IteratedContainer != &Other.IteratedContainer || BitIterator != Other.BitIterator; }
};
}
inline Iterators::FSetBitIterator begin(const ContainerImpl::FBitArray& Array) { return Iterators::FSetBitIterator(Array, 0); }
inline Iterators::FSetBitIterator end (const ContainerImpl::FBitArray& Array) { return Iterators::FSetBitIterator(Array, Array.Num()); }
template<typename T> inline Iterators::TArrayIterator<T> begin(const TArray<T>& Array) { return Iterators::TArrayIterator<T>(Array, 0); }
template<typename T> inline Iterators::TArrayIterator<T> end (const TArray<T>& Array) { return Iterators::TArrayIterator<T>(Array, Array.Num()); }
template<typename T> inline Iterators::TSparseArrayIterator<T> begin(const TSparseArray<T>& Array) { return Iterators::TSparseArrayIterator<T>(Array, Array.GetAllocationFlags(), 0); }
template<typename T> inline Iterators::TSparseArrayIterator<T> end (const TSparseArray<T>& Array) { return Iterators::TSparseArrayIterator<T>(Array, Array.GetAllocationFlags(), Array.NumAllocated()); }
template<typename T> inline Iterators::TSetIterator<T> begin(const TSet<T>& Set) { return Iterators::TSetIterator<T>(Set, Set.GetAllocationFlags(), 0); }
template<typename T> inline Iterators::TSetIterator<T> end (const TSet<T>& Set) { return Iterators::TSetIterator<T>(Set, Set.GetAllocationFlags(), Set.NumAllocated()); }
template<typename T0, typename T1> inline Iterators::TMapIterator<T0, T1> begin(const TMap<T0, T1>& Map) { return Iterators::TMapIterator<T0, T1>(Map, Map.GetAllocationFlags(), 0); }
template<typename T0, typename T1> inline Iterators::TMapIterator<T0, T1> end (const TMap<T0, T1>& Map) { return Iterators::TMapIterator<T0, T1>(Map, Map.GetAllocationFlags(), Map.NumAllocated()); }
#if defined(_WIN64)
static_assert(sizeof(TArray<int32>) == 0x10, "TArray has a wrong size!");
static_assert(sizeof(TSet<int32>) == 0x50, "TSet has a wrong size!");
static_assert(sizeof(TMap<int32, int32>) == 0x50, "TMap has a wrong size!");
#elif defined(_WIN32)
static_assert(sizeof(TArray<int32>) == 0x0C, "TArray has a wrong size!");
static_assert(sizeof(TSet<int32>) == 0x3C, "TSet has a wrong size!");
static_assert(sizeof(TMap<int32, int32>) == 0x3C, "TMap has a wrong size!");
#endif
}