13 class HashF = GFixedSizeHash<C>,
14 class AltHashF = HashF,
15 class Allocator = GAllocatorGH<C>,
16 class Entry = GHashsetCachedEntry<C, HashF>>
46 while ((
UPInt)index <= hash->table->sizeMask &&
hash->E(
index).IsEmpty()) {
63 return !(*
this == a_it);
66 [[nodiscard]]
bool IsEnd()
const
72 friend class GHashSetBase<C, HashF, AltHashF, Allocator, Entry>;
108 const C& key = ee->value;
110 UPInt hashValue = AltHashF()(key);
111 SPInt index = hashValue & hash->table->sizeMask;
113 Entry* entry = &hash->E(index);
115 if (entry->IsEmpty() || (entry->GetCachedHash(hash->table->sizeMask) != (
UPInt)index)) {
119 SPInt naturalIndex = index;
120 SPInt prevIndex = -1;
122 while ((entry->GetCachedHash(hash->table->sizeMask) != (
UPInt)naturalIndex) || !(entry->value == key)) {
124 index = entry->nextInChain;
128 entry = &hash->E(index);
132 if (naturalIndex == index) {
133 if (!entry->IsEndOfChain()) {
134 Entry* nextEntry = &hash->E(entry->nextInChain);
136 new (entry) Entry(*nextEntry);
141 hash->E(prevIndex).nextInChain = entry->nextInChain;
145 --(hash->table->entryCount);
152 friend class GHashSetBase<C, HashF, AltHashF, Allocator, Entry>;
195 for (
UPInt i = 0, n = table->sizeMask; i <= n; i++) {
196 Entry* entry = std::addressof(E(i));
197 if (!entry->IsEmpty()) {
202 Allocator::Free(table);
212 if (a_src.
IsEmpty() ==
false) {
214 for (
const_iterator it = a_src.Begin(); it != a_src.End(); ++it) {
223 for (
UPInt i = 0, n = table->sizeMask; i <= n; i++) {
224 Entry* entry = std::addressof(E(i));
225 if (!entry->IsEmpty()) {
230 Allocator::Free(table);
237 return !table || table->entryCount == 0;
240 template <
class CRef>
241 void Set(
void* a_memAddr,
const CRef& a_key)
243 UPInt hashValue = HashF()(a_key);
247 index = FindIndexCore(a_key, hashValue & table->sizeMask);
251 E(index).value = a_key;
253 Add(a_memAddr, a_key, hashValue);
257 template <
class CRef>
258 inline void Add(
void* a_memAddr,
const CRef& a_key)
260 const UPInt hashValue = HashF()(a_key);
261 Add(a_memAddr, a_key, hashValue);
271 const UPInt hashValue = AltHashF()(a_key);
272 SPInt index = hashValue & table->sizeMask;
274 Entry* entry = std::addressof(E(index));
276 if (entry->IsEmpty() || (entry->GetCachedHash(table->sizeMask) != (
UPInt)index)) {
281 const SPInt naturalIndex = index;
282 SPInt prevIndex = -1;
284 while ((entry->GetCachedHash(table->sizeMask) != (
UPInt)naturalIndex) || !(entry->value == a_key)) {
286 index = entry->nextInChain;
290 entry = std::addressof(E(index));
293 if (naturalIndex == index) {
294 if (!entry->IsEndOfChain()) {
295 Entry* nextEntry = std::addressof(E(entry->nextInChain));
297 new (entry) Entry(*nextEntry);
301 E(prevIndex).nextInChain = entry->nextInChain;
305 --(table->entryCount);
308 template <
class CRef>
317 const SPInt index = FindIndex(a_key);
319 return std::addressof(E(index).value);
326 const C*
Get(
const K& key)
const
328 const SPInt index = FindIndex(key);
330 return std::addressof(E(index).value);
339 const SPInt index = FindIndexAlt(a_key);
341 return std::addressof(E(index).value);
348 const SPInt index = FindIndexAlt(a_key);
350 return std::addressof(E(index).value);
357 bool GetAlt(
const K& a_key, C* a_val)
const
359 const SPInt index = FindIndexAlt(a_key);
362 *a_val = E(index).value;
372 return table ? 0 : (
UPInt)table->entryCount;
378 SetRawCapacity(a_memAddr, HashMinSize);
379 }
else if (table->entryCount * 5 > (table->sizeMask + 1) * 4) {
380 SetRawCapacity(a_memAddr, (table->sizeMask + 1) * 2);
391 UPInt newRawSize = (a_newSize * 5) / 4;
395 SetRawCapacity(a_memAddr, newRawSize);
405 while (idx <= table->sizeMask && E(idx).
IsEmpty()) {
429 SPInt index = FindIndex(a_key);
439 SPInt index = FindIndexAlt(a_key);
470 static_assert(
sizeof(TableType) == 0x10);
473 SPInt FindIndex(
const K& a_key)
const
478 UPInt hashValue = HashF()(a_key) & table->sizeMask;
479 return FindIndexCore(a_key, hashValue);
483 SPInt FindIndexAlt(
const K& a_key)
const
488 const UPInt hashValue = AltHashF()(a_key) & table->sizeMask;
489 return FindIndexCore(a_key, hashValue);
493 SPInt FindIndexCore(
const K& a_key,
UPInt a_hashValue)
const
496 assert((a_hashValue & ~table->sizeMask) == 0);
498 UPInt index = a_hashValue;
499 const Entry* entry = std::addressof(E(index));
501 if (entry->IsEmpty() || (entry->GetCachedHash(table->sizeMask) != index)) {
506 assert(entry->GetCachedHash(table->sizeMask) == a_hashValue);
507 if (entry->GetCachedHash(table->sizeMask) == a_hashValue && entry->value == a_key) {
510 assert(!(entry->value == a_key));
512 index = entry->nextInChain;
513 if (index == (
UPInt)-1) {
517 entry = std::addressof(E(index));
518 assert(!entry->IsEmpty());
523 template <
class CRef>
524 void Add(
void* a_memAddr,
const CRef& a_key,
UPInt a_hashValue)
527 a_hashValue &= table->sizeMask;
529 ++(table->entryCount);
531 const SPInt index = a_hashValue;
532 Entry* naturalEntry = &(E(index));
534 if (naturalEntry->IsEmpty()) {
535 new (naturalEntry) Entry(a_key, -1);
537 SPInt blankIndex = index;
539 blankIndex = (blankIndex + 1) & table->sizeMask;
540 }
while (!E(blankIndex).IsEmpty());
542 Entry* blankEntry = std::addressof(E(blankIndex));
544 if (naturalEntry->GetCachedHash(table->sizeMask) == (
UPInt)index) {
545 new (blankEntry) Entry(*naturalEntry);
546 naturalEntry->value = a_key;
547 naturalEntry->nextInChain = blankIndex;
549 SPInt collidedIndex = naturalEntry->GetCachedHash(table->sizeMask);
550 assert(collidedIndex >= 0 && collidedIndex <= (
SPInt)table->sizeMask);
552 Entry* entry = std::addressof(E(collidedIndex));
553 if (entry->nextInChain == index) {
554 new (blankEntry) Entry(*naturalEntry);
555 entry->nextInChain = blankIndex;
558 collidedIndex = entry->nextInChain;
559 assert(collidedIndex >= 0 && collidedIndex <= (
SPInt)table->sizeMask);
562 naturalEntry->value = a_key;
563 naturalEntry->nextInChain = -1;
567 naturalEntry->SetCachedHash(a_hashValue);
570 Entry& E(
UPInt a_index)
572 assert(a_index <= table->sizeMask);
573 return *(((Entry*)(table + 1)) + a_index);
576 const Entry& E(
UPInt a_index)
const
578 assert(a_index <= table->sizeMask);
579 return *(((Entry*)(table + 1)) + a_index);
582 void SetRawCapacity(
void* a_heapAddr,
UPInt a_newSize)
584 if (a_newSize == 0) {
589 if (a_newSize < HashMinSize) {
590 a_newSize = HashMinSize;
592 const auto bits =
gfchop(
glog2f((
float)(a_newSize - 1)) + 1);
593 a_newSize =
UPInt(1) << bits;
597 newHash.table =
static_cast<TableType*
>(Allocator::Alloc(a_heapAddr,
sizeof(TableType) +
sizeof(Entry) * a_newSize));
598 assert(newHash.table);
600 newHash.table->entryCount = 0;
601 newHash.table->sizeMask = a_newSize - 1;
605 for (i = 0; i < a_newSize; i++) {
606 newHash.E(i).nextInChain = -2;
610 for (i = 0, n = table->sizeMask; i <= n; ++i) {
611 Entry* entry = std::addressof(E(i));
612 if (entry->IsEmpty() ==
false) {
613 newHash.Add(a_heapAddr, entry->value);
617 Allocator::Free(table);
621 table = newHash.table;
622 newHash.table =
nullptr;
Definition: GHashSetBase.h:18
iterator begin()
Definition: GHashSetBase.h:398
const_iterator Find(const K &a_key) const
Definition: GHashSetBase.h:447
GHashSetBase(std::int32_t a_sizeHint)
Definition: GHashSetBase.h:169
GHashSetBase(void *a_memAddr, std::int32_t a_sizeHint)
Definition: GHashSetBase.h:179
bool IsEmpty() const
Definition: GHashSetBase.h:235
iterator FindAlt(const K &a_key)
Definition: GHashSetBase.h:437
void Set(void *a_memAddr, const CRef &a_key)
Definition: GHashSetBase.h:241
const C * Get(const K &key) const
Definition: GHashSetBase.h:326
const_iterator begin() const
Definition: GHashSetBase.h:416
~GHashSetBase()
Definition: GHashSetBase.h:191
void Remove(const CRef &a_key)
Definition: GHashSetBase.h:309
iterator Find(const K &a_key)
Definition: GHashSetBase.h:427
friend struct iterator
Definition: GHashSetBase.h:163
const C * GetAlt(const K &a_key) const
Definition: GHashSetBase.h:346
void Resize(void *a_memAddr, UPInt a_count)
Definition: GHashSetBase.h:384
UPInt GetSize() const
Definition: GHashSetBase.h:370
iterator end()
Definition: GHashSetBase.h:411
void SetCapacity(void *a_memAddr, UPInt a_newSize)
Definition: GHashSetBase.h:389
void Clear()
Definition: GHashSetBase.h:220
GHashSetBase< C, HashF, AltHashF, Allocator, Entry > SelfType
Definition: GHashSetBase.h:20
void RemoveAlt(const K &a_key)
Definition: GHashSetBase.h:265
C * Get(const K &a_key)
Definition: GHashSetBase.h:315
GHashSetBase([[maybe_unused]] void *a_memAddr)
Definition: GHashSetBase.h:175
C * GetAlt(const K &a_key)
Definition: GHashSetBase.h:337
bool GetAlt(const K &a_key, C *a_val) const
Definition: GHashSetBase.h:357
GFC_MEMORY_REDEFINE_NEW(GHashSetBase, Allocator::kStatID)
void Assign(void *a_memAddr, const SelfType &a_src)
Definition: GHashSetBase.h:209
void Add(void *a_memAddr, const CRef &a_key)
Definition: GHashSetBase.h:258
const_iterator end() const
Definition: GHashSetBase.h:421
GHashSetBase(const SelfType &a_src)
Definition: GHashSetBase.h:185
const_iterator FindAlt(const K &a_key) const
Definition: GHashSetBase.h:453
GHashSetBase()
Definition: GHashSetBase.h:165
void CheckExpand(void *a_memAddr)
Definition: GHashSetBase.h:375
Definition: AbsorbEffect.h:6
constexpr std::int32_t gfchop(float a_val)
Definition: GMath.h:7
std::size_t UPInt
Definition: SFTypes.h:5
std::ptrdiff_t SPInt
Definition: SFTypes.h:8
float glog2f(float a_val)
Definition: GMath.h:12
Definition: GHashSetBase.h:23
const_iterator()
Definition: GHashSetBase.h:25
void operator++()
Definition: GHashSetBase.h:42
const_iterator(const SelfType *a_hash, SPInt a_index)
Definition: GHashSetBase.h:74
bool IsEnd() const
Definition: GHashSetBase.h:66
const SelfType * hash
Definition: GHashSetBase.h:79
SPInt index
Definition: GHashSetBase.h:80
bool operator==(const const_iterator &a_it) const
Definition: GHashSetBase.h:52
bool operator!=(const const_iterator &a_it) const
Definition: GHashSetBase.h:61
const C & operator*() const
Definition: GHashSetBase.h:30
const C * operator->() const
Definition: GHashSetBase.h:36
Definition: GHashSetBase.h:87
iterator()
Definition: GHashSetBase.h:89
C & operator*() const
Definition: GHashSetBase.h:93
void Remove()
Definition: GHashSetBase.h:104
C * operator->() const
Definition: GHashSetBase.h:99