mirror of
https://github.com/Milxnor/Project-Reboot-3.0.git
synced 2026-01-14 03:02:22 +01:00
Dude 💀
This commit is contained in:
@@ -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;
|
||||
}; */
|
||||
Reference in New Issue
Block a user