19        template <std::
size_t, std::
size_t> 
class Allocator>
 
   36        static_assert(std::is_invocable_r_v<size_type, const hasher&, const key_type&>);
 
   37        static_assert(std::is_invocable_r_v<bool, const key_equal&, const key_type&, const key_type&>);
 
   42            entry_type() = 
default;
 
   43            entry_type(
const entry_type&) = 
delete;
 
   45            entry_type(entry_type&& a_rhs)  
 
   46                noexcept(std::is_nothrow_move_constructible_v<value_type>&&
 
   47                        std::is_nothrow_destructible_v<value_type>)
 
   49                if (a_rhs.has_value()) {
 
   50                    const auto rnext = a_rhs.next;
 
   51                    emplace(std::move(a_rhs).steal(), rnext);
 
   55            ~entry_type() 
noexcept { destroy(); };
 
   57            entry_type& operator=(
const entry_type&) = 
delete;
 
   59            entry_type& operator=(entry_type&& a_rhs)  
 
   60                noexcept(std::is_nothrow_move_constructible_v<value_type>&&
 
   61                        std::is_nothrow_destructible_v<value_type>)
 
   63                if (
this != std::addressof(a_rhs)) {
 
   65                    if (a_rhs.has_value()) {
 
   66                        const auto rnext = a_rhs.next;
 
   67                        emplace(std::move(a_rhs).steal(), rnext);
 
   73            [[nodiscard]] 
bool has_value() 
const noexcept { 
return next != 
nullptr; }
 
   76                noexcept(std::is_nothrow_destructible_v<value_type>)
 
   79                    std::destroy_at(std::addressof(value));
 
   86            void emplace(Arg&& a_value, 
const entry_type* a_next)  
 
   87                noexcept(std::is_nothrow_constructible_v<value_type, Arg>)
 
   89                static_assert(std::same_as<std::decay_t<Arg>, 
value_type>);
 
   91                std::construct_at(std::addressof(value), std::forward<Arg>(a_value));
 
   92                next = 
const_cast<entry_type*
>(a_next);
 
   97                noexcept(std::is_nothrow_move_constructible_v<value_type>&&
 
   98                        std::is_nothrow_destructible_v<value_type>)
 
  103                assert(!has_value());
 
  110                std::byte  buffer[
sizeof(
value_type)]{ 
static_cast<std::byte
>(0) };
 
  112            entry_type* next{ 
nullptr };
 
  119            using difference_type = std::ptrdiff_t;
 
  120            using value_type = std::remove_const_t<U>;
 
  121            using pointer = value_type*;
 
  122            using reference = value_type&;
 
  123            using iterator_category = std::forward_iterator_tag;
 
  125            iterator_base() = 
default;
 
  126            ~iterator_base() = 
default;
 
  128            iterator_base(
const volatile iterator_base&) = 
delete;
 
  129            iterator_base& operator=(
const volatile iterator_base&) = 
delete;
 
  132            iterator_base(
const iterator_base<V>& a_rhs) 
noexcept   
  133                requires(std::convertible_to<typename iterator_base<V>::reference, reference>)
 
  135                _first(a_rhs._first),
 
  140            iterator_base& operator=(
const iterator_base<V>& a_rhs) 
noexcept   
  141                requires(std::convertible_to<typename iterator_base<V>::reference, reference>)
 
  143                assert(_last == a_rhs._last);
 
  144                _first = a_rhs._first;
 
  149            [[nodiscard]] reference operator*() const noexcept
 
  152                assert(_first->has_value());
 
  153                return _first->value;
 
  157            [[nodiscard]] 
bool operator==(
const iterator_base<V>& a_rhs) 
const noexcept 
  159                assert(_last == a_rhs._last);
 
  160                return _first == a_rhs._first;
 
  163            iterator_base& operator++() noexcept
 
  169            iterator_base operator++(
int) 
noexcept 
  171                iterator_base result = *
this;
 
  176            [[nodiscard]] pointer operator->() const noexcept
 
  182            friend class BSTScatterTable;
 
  184            iterator_base(entry_type* a_first, entry_type* a_last) noexcept :
 
  188                assert(!!_first == !!_last);  
 
  189                assert(_first <= _last);
 
  190                if (iterable() && !_first->has_value()) {
 
  195            [[nodiscard]] entry_type* get_entry() const noexcept { 
return _first; }
 
  199            friend class iterator_base;
 
  201            [[nodiscard]] 
bool iterable() const noexcept { 
return _first && _last && _first != _last; }
 
  208                } 
while (_first != _last && !_first->has_value());
 
  211            entry_type* _first{ 
nullptr };
 
  212            entry_type* _last{ 
nullptr };
 
  225            requires(std::same_as<typename allocator_type::propagate_on_container_move_assignment, std::true_type>)
 
  227            _capacity(
std::exchange(a_rhs._capacity, 0)),
 
  228            _free(
std::exchange(a_rhs._free, 0)),
 
  229            _good(
std::exchange(a_rhs._good, 0)),
 
  230            _sentinel(a_rhs._sentinel),
 
  231            _allocator(
std::move(a_rhs._allocator))
 
  233            assert(a_rhs.empty());
 
 
  240            if (
this != std::addressof(a_rhs)) {
 
 
  248            requires(std::same_as<typename allocator_type::propagate_on_container_move_assignment, std::true_type>)
 
  250            if (
this != std::addressof(a_rhs)) {
 
  253                _capacity = std::exchange(a_rhs._capacity, 0);
 
  254                _free = std::exchange(a_rhs._free, 0);
 
  255                _good = std::exchange(a_rhs._good, 0);
 
  256                _sentinel = a_rhs._sentinel;
 
  257                _allocator = std::move(a_rhs._allocator);
 
  259                assert(a_rhs.empty());
 
 
  264        [[nodiscard]] 
iterator       begin() noexcept { 
return make_iterator<iterator>(get_entries()); }
 
  265        [[nodiscard]] 
const_iterator begin() const noexcept { 
return make_iterator<const_iterator>(get_entries()); }
 
  268        [[nodiscard]] 
iterator       end() noexcept { 
return make_iterator<iterator>(); }
 
  272        [[nodiscard]] 
bool      empty() const noexcept { 
return size() == 0; }
 
  278                const auto entries = get_entries();
 
  279                assert(entries != 
nullptr);
 
  280                for (
size_type i = 0; i < _capacity; ++i) {
 
  281                    entries[i].destroy();
 
 
  291        std::pair<iterator, bool> 
insert(
value_type&& a_value) { 
return do_insert(std::move(a_value)); }
 
  293        template <std::input_iterator InputIt>
 
  294        void insert(InputIt a_first, InputIt a_last)  
 
  295            requires(std::convertible_to<std::iter_reference_t<InputIt>, 
const_reference>)
 
  298            for (; a_first != a_last; ++a_first) {
 
  299                insert(*std::move(a_first));
 
 
  303        template <
class... Args>
 
  304        std::pair<iterator, bool> 
emplace(Args&&... a_args)  
 
  305            requires(std::constructible_from<
value_type, Args...>)
 
 
  315            const auto pos = 
find(a_key);
 
  316            const auto result = pos != 
end() ? 
erase(pos) : pos;
 
  317            return result != 
end() ? 1 : 0;
 
 
  327            if (a_count <= _capacity) {
 
  331            const auto oldCap = _capacity;
 
  332            const auto oldEntries = get_entries();
 
  334            const auto [newCap, newEntries] = [&]() {
 
  335                constexpr std::uint64_t min = allocator_type::min_size();
 
  336                static_assert(min > 0 && std::has_single_bit(min));
 
  337                const auto cap = std::max(std::bit_ceil<std::uint64_t>(a_count), min);
 
  339                if (cap > 1u << 31) {
 
  343                const auto entries = allocate(
static_cast<size_type>(cap));
 
  348                return std::make_pair(
static_cast<size_type>(cap), entries);
 
  351            const auto setCap = [&](
size_type a_newCap) {
 
  352                _capacity = a_newCap;
 
  357            if (newEntries == oldEntries) {
 
  358                std::uninitialized_default_construct_n(oldEntries + oldCap, newCap - oldCap);
 
  359                std::vector<value_type> todo;
 
  360                todo.reserve(
size());
 
  362                    auto& entry = oldEntries[i];
 
  363                    if (entry.has_value()) {
 
  364                        todo.emplace_back(std::move(entry).steal());
 
  369                    std::make_move_iterator(todo.begin()),
 
  370                    std::make_move_iterator(todo.end()));
 
  373                std::uninitialized_default_construct_n(newEntries, newCap);
 
  375                set_entries(newEntries);
 
  379                        auto& entry = oldEntries[i];
 
  380                        if (entry.has_value()) {
 
  381                            insert(std::move(entry).steal());
 
  384                    std::destroy_n(oldEntries, oldCap);
 
  385                    deallocate(oldEntries);
 
 
  393            return traits_type::unwrap_key(a_value);
 
  396        [[nodiscard]] entry_type* allocate(
size_type a_count)
 
  398            return static_cast<entry_type*
>(_allocator.allocate_bytes(
sizeof(entry_type) * a_count));
 
  401        void deallocate(entry_type* a_entry) { _allocator.deallocate_bytes(a_entry); }
 
  405            assert(a_pos != 
end());
 
  406            const auto entry = a_pos.get_entry();
 
  407            assert(entry != 
nullptr);
 
  408            assert(entry->has_value());
 
  410            if (entry->next == _sentinel) {  
 
  411                if (
auto prev = &get_entry_for(unwrap_key(entry->value)); prev != entry) {
 
  412                    while (prev->next != entry) {
 
  415                    prev->next = 
const_cast<entry_type*
>(_sentinel);  
 
  420                *entry = std::move(*entry->next);
 
  424            return make_iterator<iterator>(entry + 1);
 
  427        template <
class Iter>
 
  428        [[nodiscard]] Iter do_find(
const key_type& a_key) 
const   
  429            noexcept(
noexcept(hash_function(a_key)) && 
noexcept(key_eq(a_key, a_key)))
 
  432                return make_iterator<Iter>();
 
  435            auto entry = &get_entry_for(a_key);
 
  436            if (entry->has_value()) {
 
  438                    if (key_eq(unwrap_key(entry->value), a_key)) {
 
  439                        return make_iterator<Iter>(entry);
 
  443                } 
while (entry != _sentinel);
 
  446            return make_iterator<Iter>();
 
  450        [[nodiscard]] std::pair<iterator, bool> do_insert(P&& a_value)  
 
  451            requires(std::same_as<std::decay_t<P>, 
value_type>)
 
  453            if (
const auto it = 
find(unwrap_key(a_value)); it != 
end()) {  
 
  454                return std::make_pair(it, 
false);
 
  463            const auto            entry = &get_entry_for(unwrap_key(a_value));
 
  464            if (entry->has_value()) {  
 
  465                const auto free = &get_free_entry();
 
  466                const auto wouldve = &get_entry_for(unwrap_key(entry->value));
 
  467                if (wouldve == entry) {  
 
  468                    free->emplace(std::forward<P>(a_value), std::exchange(entry->next, 
free));
 
  469                    return std::make_pair(make_iterator<iterator>(
free), 
true);
 
  472                    while (prev->next != entry) {
 
  477                    *
free = std::move(*entry);
 
  479                    entry->emplace(std::forward<P>(a_value), _sentinel);
 
  481                    return std::make_pair(make_iterator<iterator>(entry), 
true);
 
  484                entry->emplace(std::forward<P>(a_value), _sentinel);
 
  485                return std::make_pair(make_iterator<iterator>(entry), 
true);
 
  489        void free_resources()
 
  492                assert(get_entries() != 
nullptr);
 
  493                std::destroy_n(get_entries(), _capacity);
 
  494                deallocate(get_entries());
 
  495                set_entries(
nullptr);
 
  501            assert(get_entries() == 
nullptr);
 
  502            assert(_capacity == 0);
 
  506        [[nodiscard]] entry_type& get_entry_for(
const key_type& a_key) 
const   
  507            noexcept(
noexcept(hash_function(a_key)))
 
  509            assert(get_entries() != 
nullptr);
 
  510            assert(std::has_single_bit(_capacity));
 
  512            const auto hash = hash_function(a_key);
 
  513            const auto idx = hash & (_capacity - 1);  
 
  514            return get_entries()[idx];
 
  517        [[nodiscard]] entry_type* get_entries() const noexcept { 
return static_cast<entry_type*
>(_allocator.get_entries()); }
 
  519        [[nodiscard]] entry_type& get_free_entry() noexcept
 
  522            assert(get_entries() != 
nullptr);
 
  523            assert(std::has_single_bit(_capacity));
 
  524            assert([&]() 
noexcept {
 
  525                const auto begin = get_entries();
 
  526                const auto end = get_entries() + _capacity;
 
  530                           [](
const auto& a_entry) 
noexcept {
 
  531                               return !a_entry.has_value();
 
  535            const auto entries = get_entries();
 
  536            while (entries[_good].has_value()) {
 
  537                _good = (_good + 1) & (_capacity - 1);  
 
  539            return entries[_good];
 
  543            noexcept(std::is_nothrow_constructible_v<hasher>&&
 
  544                    std::is_nothrow_invocable_v<const hasher&, const key_type&>)
 
  549        [[nodiscard]] 
bool key_eq(
const key_type& a_lhs, 
const key_type& a_rhs) 
const   
  550            noexcept(std::is_nothrow_constructible_v<key_equal>&&
 
  551                    std::is_nothrow_invocable_v<const key_equal&, const key_type&, const key_type&>)
 
  553            return static_cast<bool>(
key_equal()(a_lhs, a_rhs));
 
  556        template <
class Iter>
 
  557        [[nodiscard]] Iter make_iterator() const noexcept
 
  559            return Iter(get_entries() + _capacity, get_entries() + _capacity);
 
  562        template <
class Iter>
 
  563        [[nodiscard]] Iter make_iterator(entry_type* a_first) 
const noexcept 
  565            return Iter(a_first, get_entries() + _capacity);
 
  568        void set_entries(entry_type* a_entries) 
noexcept { _allocator.set_entries(a_entries); }
 
  571        std::uint64_t     _pad00{ 0 };                                                                        
 
  572        std::uint32_t     _pad08{ 0 };                                                                        
 
 
  580    template <
class Key, 
class T>
 
  602    template <std::
size_t S, std::
size_t A>
 
  613            _entries(std::exchange(a_rhs._entries, 
nullptr))
 
 
  621            if (
this != std::addressof(a_rhs)) {
 
  622                assert(_entries == 
nullptr);
 
  623                _entries = std::exchange(a_rhs._entries, 
nullptr);
 
 
  632            assert(a_bytes % S == 0);
 
 
  638        [[nodiscard]] 
void* 
get_entries() const noexcept { 
return _entries; }
 
  639        void                set_entries(
void* a_entries) 
noexcept { _entries = 
static_cast<std::byte*
>(a_entries); }
 
  643        std::uint64_t _pad00{ 0 };          
 
  644        std::byte*    _entries{ 
nullptr };  
 
 
  647    template <std::u
int32_t N>
 
  651        static_assert(N > 0 && std::has_single_bit(N));
 
  653        template <std::
size_t S, std::
size_t A>
 
  671                assert(a_bytes % S == 0);
 
  672                return a_bytes <= N * S ? _buffer : 
nullptr;
 
 
  677            [[nodiscard]] 
void* 
get_entries() const noexcept { 
return _entries; }
 
  681                assert(a_entries == _buffer || a_entries == 
nullptr);
 
  682                _entries = 
static_cast<std::byte*
>(a_entries);
 
 
  686            alignas(A) std::byte _buffer[N * S]{ 
static_cast<std::byte
>(0) };  
 
  687            std::byte* _entries{ 
nullptr };                                    
 
 
 
  691    template <std::
size_t S, std::
size_t A>
 
  709            assert(_allocator != 
nullptr);
 
  710            assert(a_bytes % S == 0);
 
  711            return _allocator->
Allocate(a_bytes, 0x10);
 
 
  716            assert(_allocator != 
nullptr);
 
 
  720        [[nodiscard]] 
void* 
get_entries() const noexcept { 
return _entries; }
 
  721        void                set_entries(
void* a_entries) 
noexcept { _entries = 
static_cast<std::byte*
>(a_entries); }
 
  726        std::byte* _entries{ 
nullptr };                                                
 
 
  732        class Hash = BSCRC32<Key>,
 
  733        class KeyEq = std::equal_to<Key>>
 
  744        static_assert(std::forward_iterator<_dummy_bsthashmap::iterator>);
 
  749        class Hash = BSCRC32<Key>,
 
  750        class KeyEq = std::equal_to<Key>>
 
  763        class KeyEq = std::equal_to<Key>>
 
  775        class KeyEq = std::equal_to<Key>>
 
Definition BSTHashMap.h:693
BSTScatterTableScrapAllocator(const BSTScatterTableScrapAllocator &)=delete
void * allocate_bytes(std::size_t a_bytes)
Definition BSTHashMap.h:707
void deallocate_bytes(void *a_ptr)
Definition BSTHashMap.h:714
std::uint32_t size_type
Definition BSTHashMap.h:695
void * get_entries() const noexcept
Definition BSTHashMap.h:720
static constexpr size_type min_size() noexcept
Definition BSTHashMap.h:705
~BSTScatterTableScrapAllocator()=default
BSTScatterTableScrapAllocator(BSTScatterTableScrapAllocator &&)=delete
BSTScatterTableScrapAllocator & operator=(const BSTScatterTableScrapAllocator &)=delete
std::false_type propagate_on_container_move_assignment
Definition BSTHashMap.h:696
void set_entries(void *a_entries) noexcept
Definition BSTHashMap.h:721
BSTScatterTableScrapAllocator & operator=(BSTScatterTableScrapAllocator &&)=delete
BSTScatterTableScrapAllocator()=default
Definition BSTHashMap.h:582
static const key_type & unwrap_key(const value_type &a_value) noexcept
Definition BSTHashMap.h:588
Key key_type
Definition BSTHashMap.h:584
T mapped_type
Definition BSTHashMap.h:585
Definition BSTHashMap.h:21
const value_type & const_reference
Definition BSTHashMap.h:32
typename Traits::mapped_type mapped_type
Definition BSTHashMap.h:25
std::pair< iterator, bool > emplace(Args &&... a_args)
Definition BSTHashMap.h:304
std::uint32_t size_type
Definition BSTHashMap.h:27
KeyEqual key_equal
Definition BSTHashMap.h:30
void insert(InputIt a_first, InputIt a_last)
Definition BSTHashMap.h:294
std::pair< iterator, bool > insert(value_type &&a_value)
Definition BSTHashMap.h:291
iterator end() noexcept
Definition BSTHashMap.h:268
void reserve(size_type a_count)
Definition BSTHashMap.h:325
const_iterator end() const noexcept
Definition BSTHashMap.h:269
iterator begin() noexcept
Definition BSTHashMap.h:264
BSTScatterTable(BSTScatterTable &&a_rhs) noexcept
Definition BSTHashMap.h:224
~BSTScatterTable()
Definition BSTHashMap.h:236
void clear()
Definition BSTHashMap.h:275
value_type & reference
Definition BSTHashMap.h:31
const_iterator cbegin() const noexcept
Definition BSTHashMap.h:266
std::int32_t difference_type
Definition BSTHashMap.h:28
size_type size() const noexcept
Definition BSTHashMap.h:273
Hash hasher
Definition BSTHashMap.h:29
BSTScatterTable & operator=(const BSTScatterTable &a_rhs)
Definition BSTHashMap.h:238
typename Traits::key_type key_type
Definition BSTHashMap.h:24
iterator erase(const_iterator a_pos)
Definition BSTHashMap.h:310
const_iterator begin() const noexcept
Definition BSTHashMap.h:265
iterator_base< value_type > iterator
Definition BSTHashMap.h:217
Allocator< sizeof(entry_type), alignof(entry_type)> allocator_type
Definition BSTHashMap.h:216
const_iterator find(const key_type &a_key) const
Definition BSTHashMap.h:321
const_iterator cend() const noexcept
Definition BSTHashMap.h:270
value_type * pointer
Definition BSTHashMap.h:33
BSTScatterTable()=default
const value_type * const_pointer
Definition BSTHashMap.h:34
BSTScatterTable(const BSTScatterTable &a_rhs)
Definition BSTHashMap.h:222
Traits traits_type
Definition BSTHashMap.h:23
iterator_base< const value_type > const_iterator
Definition BSTHashMap.h:218
BSTScatterTable & operator=(BSTScatterTable &&a_rhs)
Definition BSTHashMap.h:247
typename Traits::value_type value_type
Definition BSTHashMap.h:26
bool contains(const key_type &a_key) const
Definition BSTHashMap.h:323
std::pair< iterator, bool > insert(const value_type &a_value)
Definition BSTHashMap.h:290
iterator erase(iterator a_pos)
Definition BSTHashMap.h:311
size_type erase(const key_type &a_key)
Definition BSTHashMap.h:313
bool empty() const noexcept
Definition BSTHashMap.h:272
iterator find(const key_type &a_key)
Definition BSTHashMap.h:320
Definition BSTHashMap.h:593
static const key_type & unwrap_key(const value_type &a_value) noexcept
Definition BSTHashMap.h:599
key_type value_type
Definition BSTHashMap.h:597
Key key_type
Definition BSTHashMap.h:595
void mapped_type
Definition BSTHashMap.h:596
static MemoryManager * GetSingleton()
Definition MemoryManager.h:29
ScrapHeap * GetThreadScrapHeap()
Definition MemoryManager.h:50
Definition ScrapHeap.h:10
void * Allocate(std::size_t a_size, std::size_t a_alignment)
void Deallocate(void *a_mem)
static constexpr std::uint8_t BSTScatterTableSentinel[]
Definition BSTHashMap.h:11
Definition AbsorbEffect.h:6
std::uintptr_t UnkValue
Definition BSTHashMap.h:784
T * malloc()
Definition MemoryManager.h:113
constexpr bool operator==(const BSTSmartPointer< T1 > &a_lhs, const BSTSmartPointer< T2 > &a_rhs)
Definition BSTSmartPointer.h:241
void free(void *a_ptr)
Definition MemoryManager.h:187
std::uintptr_t UnkKey
Definition BSTHashMap.h:783
void report_and_fail(std::string_view a_msg, std::source_location a_loc=std::source_location::current())
Definition PCH.h:397
Definition EffectArchetypes.h:65
Definition BSTHashMap.h:604
void * get_entries() const noexcept
Definition BSTHashMap.h:638
void * allocate_bytes(std::size_t a_bytes)
Definition BSTHashMap.h:630
~BSTScatterTableHeapAllocator()=default
BSTScatterTableHeapAllocator & operator=(const BSTScatterTableHeapAllocator &)=delete
std::true_type propagate_on_container_move_assignment
Definition BSTHashMap.h:607
BSTScatterTableHeapAllocator & operator=(BSTScatterTableHeapAllocator &&a_rhs) noexcept
Definition BSTHashMap.h:619
BSTScatterTableHeapAllocator(BSTScatterTableHeapAllocator &&a_rhs) noexcept
Definition BSTHashMap.h:612
BSTScatterTableHeapAllocator()=default
BSTScatterTableHeapAllocator(const BSTScatterTableHeapAllocator &)=delete
void deallocate_bytes(void *a_ptr)
Definition BSTHashMap.h:636
static constexpr size_type min_size() noexcept
Definition BSTHashMap.h:628
void set_entries(void *a_entries) noexcept
Definition BSTHashMap.h:639
std::uint32_t size_type
Definition BSTHashMap.h:606
Definition BSTHashMap.h:655
Allocator(const Allocator &)=delete
std::false_type propagate_on_container_move_assignment
Definition BSTHashMap.h:658
void * get_entries() const noexcept
Definition BSTHashMap.h:677
Allocator & operator=(Allocator &&)=delete
static constexpr size_type min_size() noexcept
Definition BSTHashMap.h:667
Allocator & operator=(const Allocator &)=delete
void deallocate_bytes(void *a_ptr)
Definition BSTHashMap.h:675
void set_entries(void *a_entries) noexcept
Definition BSTHashMap.h:679
std::uint32_t size_type
Definition BSTHashMap.h:657
void * allocate_bytes(std::size_t a_bytes)
Definition BSTHashMap.h:669
Allocator(Allocator &&)=delete
Definition BSTHashMap.h:649