Dude 💀

This commit is contained in:
Gray
2024-03-20 21:45:38 -04:00
parent 138d3cc668
commit b3d9ab9e8b
46 changed files with 2846 additions and 1608 deletions

View File

@@ -1,6 +1,10 @@
// Copied from 4.19
#pragma once
#include "SparseArray.h"
#include "ChooseClass.h"
#include "UnrealTypeTraits.h"
template <typename ElementType>
class TSetElement
@@ -32,112 +36,434 @@ public:
}
};
template <typename SetType>
/** Either NULL or an identifier for an element of a set. */
class FSetElementId
{
public:
template<typename, typename, typename>
friend class TSet;
friend class FScriptSet;
/** Default constructor. */
FORCEINLINE FSetElementId() :
Index(INDEX_NONE)
{}
/** @return a boolean value representing whether the id is NULL. */
FORCEINLINE bool IsValidId() const
{
return Index != INDEX_NONE;
}
/** Comparison operator. */
FORCEINLINE friend bool operator==(const FSetElementId& A, const FSetElementId& B)
{
return A.Index == B.Index;
}
FORCEINLINE int32 AsInteger() const
{
return Index;
}
FORCEINLINE static FSetElementId FromInteger(int32 Integer)
{
return FSetElementId(Integer);
}
private:
/** The index of the element in the set's element array. */
int32 Index;
/** Initialization constructor. */
FORCEINLINE FSetElementId(int32 InIndex) :
Index(InIndex)
{}
/** Implicit conversion to the element index. */
FORCEINLINE operator int32() const
{
return Index;
}
};
template<typename ElementType, typename InKeyType, bool bInAllowDuplicateKeys = false>
struct BaseKeyFuncs
{
typedef InKeyType KeyType;
typedef typename TCallTraits<InKeyType>::ParamType KeyInitType;
typedef typename TCallTraits<ElementType>::ParamType ElementInitType;
enum { bAllowDuplicateKeys = bInAllowDuplicateKeys };
};
/**
* A default implementation of the KeyFuncs used by TSet which uses the element as a key.
*/
template<typename ElementType, bool bInAllowDuplicateKeys = false>
struct DefaultKeyFuncs : BaseKeyFuncs<ElementType, ElementType, bInAllowDuplicateKeys>
{
typedef typename TCallTraits<ElementType>::ParamType KeyInitType;
typedef typename TCallTraits<ElementType>::ParamType ElementInitType;
/**
* @return The key used to index the given element.
*/
static FORCEINLINE KeyInitType GetSetKey(ElementInitType Element)
{
return Element;
}
/**
* @return True if the keys match.
*/
static FORCEINLINE bool Matches(KeyInitType A, KeyInitType B)
{
return A == B;
}
/** Calculates a hash index for a key. */
static FORCEINLINE uint32 GetKeyHash(KeyInitType Key)
{
return GetTypeHash(Key);
}
};
template<
typename InElementType,
typename KeyFuncs = DefaultKeyFuncs<InElementType>,
typename Allocator = FDefaultSetAllocator
>
class TSet;
template<
typename InElementType,
typename KeyFuncs /*= DefaultKeyFuncs<ElementType>*/,
typename Allocator /*= FDefaultSetAllocator*/
>
class TSet
{
private:
friend TSparseArray;
public:
typedef TSetElement<SetType> ElementType;
typedef TSparseArrayElementOrListLink<ElementType> ArrayElementType;
typedef typename KeyFuncs::KeyInitType KeyInitType;
typedef typename KeyFuncs::ElementInitType ElementInitType;
typedef TSetElement<InElementType> SetElementType;
typedef InElementType ElementType;
public:
typedef TSparseArray<SetElementType, typename Allocator::SparseArrayAllocator> ElementArrayType;
typedef typename Allocator::HashAllocator::template ForElementType<FSetElementId> HashType;
ElementArrayType Elements;
mutable HashType Hash;
mutable int32 HashSize;
FORCEINLINE FSetElementId& GetTypedHash(int32 HashIndex) const
{
return ((FSetElementId*)Hash.GetAllocation())[HashIndex & (HashSize - 1)];
}
public:
TSparseArray<ElementType> Elements;
FORCEINLINE ElementType* Find(KeyInitType Key)
{
FSetElementId ElementId = FindId(Key);
if (ElementId.IsValidId())
{
return &Elements[ElementId].Value;
}
else
{
return NULL;
}
}
mutable TInlineAllocator<1>::ForElementType<int> Hash;
mutable int32 HashSize;
/**
* Finds an element with the given key in the set.
* @param Key - The key to search for.
* @return A const pointer to an element with the given key. If no element in the set has the given key, this will return NULL.
*/
FORCEINLINE const ElementType* Find(KeyInitType Key) const
{
FSetElementId ElementId = FindId(Key);
if (ElementId.IsValidId())
{
return &Elements[ElementId].Value;
}
else
{
return NULL;
}
}
public:
class FBaseIterator
/** Adds an element to the hash. */
FORCEINLINE void HashElement(FSetElementId ElementId, const SetElementType& Element) const
{
// Compute the hash bucket the element goes in.
Element.HashIndex = KeyFuncs::GetKeyHash(KeyFuncs::GetSetKey(Element.Value)) & (HashSize - 1);
// Link the element into the hash bucket.
Element.HashNextId = GetTypedHash(Element.HashIndex);
GetTypedHash(Element.HashIndex) = ElementId;
}
/**
* Checks if the hash has an appropriate number of buckets, and if not resizes it.
* @param NumHashedElements - The number of elements to size the hash for.
* @param bAllowShrinking - true if the hash is allowed to shrink.
* @return true if the set was rehashed.
*/
bool ConditionalRehash(int32 NumHashedElements, bool bAllowShrinking = false) const
{
// Calculate the desired hash size for the specified number of elements.
const int32 DesiredHashSize = Allocator::GetNumberOfHashBuckets(NumHashedElements);
// If the hash hasn't been created yet, or is smaller than the desired hash size, rehash.
if (NumHashedElements > 0 &&
(!HashSize ||
HashSize < DesiredHashSize ||
(HashSize > DesiredHashSize && bAllowShrinking)))
{
HashSize = DesiredHashSize;
Rehash();
return true;
}
else
{
return false;
}
}
/** Resizes the hash. */
void Rehash() const
{
// Free the old hash.
Hash.ResizeAllocation(0, 0, sizeof(FSetElementId));
int32 LocalHashSize = HashSize;
if (LocalHashSize)
{
// Allocate the new hash.
// checkSlow(FMath::IsPowerOfTwo(HashSize));
Hash.ResizeAllocation(0, LocalHashSize, sizeof(FSetElementId));
for (int32 HashIndex = 0; HashIndex < LocalHashSize; ++HashIndex)
{
GetTypedHash(HashIndex) = FSetElementId();
}
// Add the existing elements to the new hash.
for (typename ElementArrayType::TConstIterator ElementIt(Elements); ElementIt; ++ElementIt)
{
HashElement(FSetElementId(ElementIt.GetIndex()), *ElementIt);
}
}
}
template<bool bConst, bool bRangedFor = false>
class TBaseIterator
{
private:
TSet<SetType>& IteratedSet;
TSparseArray<ElementType>::FBaseIterator ElementIt;
friend class TSet;
typedef typename TChooseClass<bConst, const ElementType, ElementType>::Result ItElementType;
public:
FORCEINLINE FBaseIterator(const TSet<SetType>& InSet, TSparseArray<TSetElement<SetType>>::FBaseIterator InElementIt)
: IteratedSet(const_cast<TSet<SetType>&>(InSet))
, ElementIt(InElementIt)
typedef typename TChooseClass<
bConst,
typename TChooseClass<bRangedFor, typename ElementArrayType::TRangedForConstIterator, typename ElementArrayType::TConstIterator>::Result,
typename TChooseClass<bRangedFor, typename ElementArrayType::TRangedForIterator, typename ElementArrayType::TIterator >::Result
>::Result ElementItType;
FORCEINLINE TBaseIterator(const ElementItType& InElementIt)
: ElementIt(InElementIt)
{
}
FORCEINLINE explicit operator bool() const
{
return (bool)ElementIt;
}
FORCEINLINE TSet<SetType>::FBaseIterator& operator++()
/** Advances the iterator to the next element. */
FORCEINLINE TBaseIterator& operator++()
{
++ElementIt;
return *this;
}
FORCEINLINE bool operator==(const TSet<SetType>::FBaseIterator& OtherIt) const
/** conversion to "bool" returning true if the iterator is valid. */
FORCEINLINE explicit operator bool() const
{
return ElementIt == OtherIt.ElementIt;
return !!ElementIt;
}
FORCEINLINE bool operator!=(const TSet<SetType>::FBaseIterator& OtherIt) const
/** inverse of the "bool" operator */
FORCEINLINE bool operator !() const
{
return ElementIt != OtherIt.ElementIt;
return !(bool)*this;
}
FORCEINLINE TSet<SetType>::FBaseIterator& operator=(TSet<SetType>::FBaseIterator& OtherIt)
// Accessors.
FORCEINLINE FSetElementId GetId() const
{
return ElementIt = OtherIt.ElementIt;
return TSet::IndexToId(ElementIt.GetIndex());
}
FORCEINLINE SetType& operator*()
FORCEINLINE ItElementType* operator->() const
{
return (*ElementIt).Value;
return &ElementIt->Value;
}
FORCEINLINE const SetType& operator*() const
FORCEINLINE ItElementType& operator*() const
{
return &((*ElementIt).Value);
return ElementIt->Value;
}
FORCEINLINE SetType* operator->()
FORCEINLINE friend bool operator==(const TBaseIterator& Lhs, const TBaseIterator& Rhs) { return Lhs.ElementIt == Rhs.ElementIt; }
FORCEINLINE friend bool operator!=(const TBaseIterator& Lhs, const TBaseIterator& Rhs) { return Lhs.ElementIt != Rhs.ElementIt; }
ElementItType ElementIt;
};
/** The base type of whole set iterators. */
template<bool bConst>
class TBaseKeyIterator
{
private:
typedef typename TChooseClass<bConst, const TSet, TSet>::Result SetType;
typedef typename TChooseClass<bConst, const ElementType, ElementType>::Result ItElementType;
public:
/** Initialization constructor. */
FORCEINLINE TBaseKeyIterator(SetType& InSet, KeyInitType InKey)
: Set(InSet)
, Key(InKey)
, Id()
{
return &((*ElementIt).Value);
// The set's hash needs to be initialized to find the elements with the specified key.
Set.ConditionalRehash(Set.Elements.Num());
if (Set.HashSize)
{
NextId = Set.GetTypedHash(KeyFuncs::GetKeyHash(Key));
++(*this);
}
/* // Milxnor: This is only on newer builds?
else
{
NextIndex = INDEX_NONE;
}
*/
}
FORCEINLINE const SetType* operator->() const
/** Advances the iterator to the next element. */
FORCEINLINE TBaseKeyIterator& operator++()
{
return &(*ElementIt).Value;
Id = NextId;
while (Id.IsValidId())
{
NextId = Set.GetInternalElement(Id).HashNextId;
// checkSlow(Id != NextId);
if (KeyFuncs::Matches(KeyFuncs::GetSetKey(Set[Id]), Key))
{
break;
}
Id = NextId;
}
return *this;
}
FORCEINLINE const int32 GetIndex() const
/** conversion to "bool" returning true if the iterator is valid. */
FORCEINLINE explicit operator bool() const
{
return ElementIt.GetIndex();
return Id.IsValidId();
}
FORCEINLINE ElementType& GetSetElement()
/** inverse of the "bool" operator */
FORCEINLINE bool operator !() const
{
return *ElementIt;
return !(bool)*this;
}
FORCEINLINE const ElementType& GetSetElement() const
// Accessors.
FORCEINLINE ItElementType* operator->() const
{
return *ElementIt;
return &Set[Id];
}
FORCEINLINE bool IsElementValid() const
FORCEINLINE ItElementType& operator*() const
{
return Set[Id];
}
protected:
SetType& Set;
typename TTypeTraits<typename KeyFuncs::KeyType>::ConstPointerType Key;
FSetElementId Id;
FSetElementId NextId;
};
FORCEINLINE const SetElementType& GetInternalElement(FSetElementId Id) const
{
return Elements[Id];
}
FORCEINLINE SetElementType& GetInternalElement(FSetElementId Id)
{
return Elements[Id];
}
public:
class TConstIterator : public TBaseIterator<true>
{
friend class TSet;
public:
FORCEINLINE TConstIterator(const TSet& InSet)
: TBaseIterator<true>(begin(InSet.Elements))
{
return ElementIt.IsElementValid();
}
};
public:
FORCEINLINE TSet<SetType>::FBaseIterator begin()
class TIterator : public TBaseIterator<false>
{
return TSet<SetType>::FBaseIterator(*this, Elements.begin());
}
FORCEINLINE const TSet<SetType>::FBaseIterator begin() const
friend class TSet;
public:
FORCEINLINE TIterator(TSet& InSet)
: TBaseIterator<false>(begin(InSet.Elements))
, Set(InSet)
{
}
/** Removes the current element from the set. */
/* // T(R)
FORCEINLINE void RemoveCurrent()
{
Set.Remove(TBaseIterator<false>::GetId());
}
*/
private:
TSet& Set;
};
using TRangedForConstIterator = TBaseIterator<true, true>;
using TRangedForIterator = TBaseIterator<false, true>;
static FORCEINLINE FSetElementId IndexToId(int32 Index)
{
return TSet<SetType>::FBaseIterator(*this, Elements.begin());
}
FORCEINLINE TSet<SetType>::FBaseIterator end()
{
return TSet<SetType>::FBaseIterator(*this, Elements.end());
}
FORCEINLINE const TSet<SetType>::FBaseIterator end() const
{
return TSet<SetType>::FBaseIterator(*this, Elements.end());
return FSetElementId(Index);
}
FORCEINLINE SetType& operator[](int Index)
/** Creates an iterator for the contents of this set */
FORCEINLINE TIterator CreateIterator()
{
return Elements[Index].ElementData.Value;
return TIterator(*this);
}
/** Creates a const iterator for the contents of this set */
FORCEINLINE TConstIterator CreateConstIterator() const
{
return TConstIterator(*this);
}
FORCEINLINE int32 Num() const
@@ -156,65 +482,39 @@ public:
{
return Elements;
}
FORCEINLINE const TBitArray& GetAllocationFlags() const
{
return Elements.GetAllocationFlags();
}
FORCEINLINE bool IsIndexValid(int32 IndexToCheck) const
{
return Elements.IsIndexValid(IndexToCheck);
}
FORCEINLINE const bool Contains(const SetType& ElementToLookFor) const
FSetElementId FindId(KeyInitType Key) const
{
if (Num() <= 0)
return false;
for (SetType Element : *this)
if (Elements.Num())
{
if (Element == ElementToLookFor)
return true;
}
return false;
}
FORCEINLINE const int32 Find(const SetType& ElementToLookFor) const
{
for (auto It = this->begin(); It != this->end(); ++It)
{
if (*It == ElementToLookFor)
for (FSetElementId ElementId = GetTypedHash(KeyFuncs::GetKeyHash(Key));
ElementId.IsValidId();
ElementId = Elements[ElementId].HashNextId)
{
return It.GetIndex();
if (KeyFuncs::Matches(KeyFuncs::GetSetKey(Elements[ElementId].Value), Key))
{
return ElementId;
}
}
}
return -1;
return FSetElementId();
}
FORCEINLINE bool Remove(const SetType& ElementToRemove)
FORCEINLINE bool Contains(KeyInitType Key) const
{
auto Idx = Find(ElementToRemove);
if (Idx == -1)
return false;
Elements.RemoveAt(Idx);
return true;
}
FORCEINLINE bool Remove(int Index)
{
Elements.RemoveAt(Index);
return true;
return FindId(Key).IsValidId();
}
private:
/**
* DO NOT USE DIRECTLY
* STL-like iterators to enable range-based for loop support.
*/
FORCEINLINE friend TRangedForIterator begin(TSet& Set) { return TRangedForIterator(begin(Set.Elements)); }
FORCEINLINE friend TRangedForConstIterator begin(const TSet& Set) { return TRangedForConstIterator(begin(Set.Elements)); }
FORCEINLINE friend TRangedForIterator end(TSet& Set) { return TRangedForIterator(end(Set.Elements)); }
FORCEINLINE friend TRangedForConstIterator end(const TSet& Set) { return TRangedForConstIterator(end(Set.Elements)); }
};
/* template<typename InElementType> //, typename KeyFuncs, typename Allocator>
class TSet
{
public:
typedef TSetElement<InElementType> ElementType;
typedef TSparseArrayElementOrListLink<ElementType> ArrayElementType;
TSparseArray<ElementType> Elements;
mutable TInlineAllocator<1>::ForElementType<int> Hash;
mutable int32 HashSize;
}; */