mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-30 14:30:53 -07:00 
			
		
		
		
	Hashtable done
This commit is contained in:
		| @@ -38,8 +38,7 @@ template<class Type> bool         resize(Array<Type>& array, usize num); | |||||||
| template<class Type> bool         set_capacity(Array<Type>& array, usize new_capacity); | template<class Type> bool         set_capacity(Array<Type>& array, usize new_capacity); | ||||||
| template<class Type> ArrayHeader* get_header(Array<Type>& array); | template<class Type> ArrayHeader* get_header(Array<Type>& array); | ||||||
|  |  | ||||||
| struct ArrayHeader | struct ArrayHeader { | ||||||
| { |  | ||||||
| 	AllocatorInfo Allocator; | 	AllocatorInfo Allocator; | ||||||
| 	usize         Capacity; | 	usize         Capacity; | ||||||
| 	usize         Num; | 	usize         Num; | ||||||
| @@ -83,8 +82,7 @@ struct Array | |||||||
| }; | }; | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| Array<Type> array_init(AllocatorInfo allocator) | Array<Type> array_init(AllocatorInfo allocator) { | ||||||
| { |  | ||||||
| 	return array_init_reserve<Type>(allocator, array_grow_formula<Type>(0)); | 	return array_init_reserve<Type>(allocator, array_grow_formula<Type>(0)); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -104,14 +102,12 @@ Array<Type> array_init_reserve(AllocatorInfo allocator, ssize capacity) | |||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| usize array_grow_formula(ssize value) | usize array_grow_formula(ssize value) { | ||||||
| { |  | ||||||
| 	return 2 * value + 8; | 	return 2 * value + 8; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| bool append(Array<Type>& array, Array<Type> other) | bool append(Array<Type>& array, Array<Type> other) { | ||||||
| { |  | ||||||
| 	return append(array, other, num(other)); | 	return append(array, other, num(other)); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -124,7 +120,6 @@ bool append(Array<Type>& array, Type value) | |||||||
| 	{ | 	{ | ||||||
| 		if (!grow(array, header->Capacity)) | 		if (!grow(array, header->Capacity)) | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| 		header = get_header(array); | 		header = get_header(array); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -143,7 +138,6 @@ bool append(Array<Type>& array, Type* items, usize item_num) | |||||||
| 	{ | 	{ | ||||||
| 		if (!grow(array, header->Capacity + item_num)) | 		if (!grow(array, header->Capacity + item_num)) | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| 		header = get_header(array); | 		header = get_header(array); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -209,15 +203,13 @@ bool append_at(Array<Type>& array, Type* items, usize item_num, usize idx) | |||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| Type& back(Array<Type>& array) | Type& back(Array<Type>& array) { | ||||||
| { |  | ||||||
| 	ArrayHeader* header = get_header(array); | 	ArrayHeader* header = get_header(array); | ||||||
| 	return array.Data[header->Num - 1]; | 	return array.Data[header->Num - 1]; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| void clear(Array<Type>& array) | void clear(Array<Type>& array) { | ||||||
| { |  | ||||||
| 	ArrayHeader* header = get_header(array); | 	ArrayHeader* header = get_header(array); | ||||||
| 	header->Num = 0; | 	header->Num = 0; | ||||||
| } | } | ||||||
| @@ -239,16 +231,14 @@ bool fill(Array<Type>& array, usize begin, usize end, Type value) | |||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| void free(Array<Type>& array) | void free(Array<Type>& array) { | ||||||
| { |  | ||||||
| 	ArrayHeader* header = get_header(array); | 	ArrayHeader* header = get_header(array); | ||||||
| 	gen::free(header->Allocator, header); | 	gen::free(header->Allocator, header); | ||||||
| 	array.Data = nullptr; | 	array.Data = nullptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| ArrayHeader* get_header(Array<Type>& array) | ArrayHeader* get_header(Array<Type>& array) { | ||||||
| { |  | ||||||
| 	using NonConstType = TRemoveConst<Type>; | 	using NonConstType = TRemoveConst<Type>; | ||||||
| 	return rcast(ArrayHeader*, const_cast<NonConstType*>(array.Data)) - 1; | 	return rcast(ArrayHeader*, const_cast<NonConstType*>(array.Data)) - 1; | ||||||
| } | } | ||||||
| @@ -266,14 +256,12 @@ bool grow(Array<Type>& array, usize min_capacity) | |||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| usize num(Array<Type>& array) | usize num(Array<Type>& array) { | ||||||
| { |  | ||||||
| 	return get_header(array)->Num; | 	return get_header(array)->Num; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| void pop(Array<Type>& array) | void pop(Array<Type>& array) { | ||||||
| { |  | ||||||
| 	ArrayHeader* header = get_header(array); | 	ArrayHeader* header = get_header(array); | ||||||
| 	GEN_ASSERT(header->Num > 0); | 	GEN_ASSERT(header->Num > 0); | ||||||
| 	header->Num--; | 	header->Num--; | ||||||
| @@ -305,11 +293,9 @@ bool resize(Array<Type>& array, usize num) | |||||||
| { | { | ||||||
| 	ArrayHeader* header = get_header(array); | 	ArrayHeader* header = get_header(array); | ||||||
|  |  | ||||||
|     if (header->Capacity < num) | 	if (header->Capacity < num) { | ||||||
|     { |  | ||||||
| 		if (!grow(array, num)) | 		if (!grow(array, num)) | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| 		header = get_header(array); | 		header = get_header(array); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -341,7 +327,7 @@ bool set_capacity(Array<Type>& array, usize new_capacity) | |||||||
|  |  | ||||||
| 	new_header->Capacity = new_capacity; | 	new_header->Capacity = new_capacity; | ||||||
|  |  | ||||||
|     gen::free(header->Allocator, header); | 	GEN_NS free(header->Allocator, header); | ||||||
|  |  | ||||||
| 	array.Data = rcast(Type*, new_header + 1); | 	array.Data = rcast(Type*, new_header + 1); | ||||||
| 	return true; | 	return true; | ||||||
| @@ -350,34 +336,78 @@ bool set_capacity(Array<Type>& array, usize new_capacity) | |||||||
|  |  | ||||||
| // TODO(Ed) : This thing needs ALOT of work. | // TODO(Ed) : This thing needs ALOT of work. | ||||||
|  |  | ||||||
| template<typename Type> | #pragma region HashTable | ||||||
| struct HashTable | template<class Type> struct HashTable; | ||||||
| { |  | ||||||
| 	struct FindResult | struct HashTableFindResult { | ||||||
| 	{ |  | ||||||
| 	ssize HashIndex; | 	ssize HashIndex; | ||||||
| 	ssize PrevIndex; | 	ssize PrevIndex; | ||||||
| 	ssize EntryIndex; | 	ssize EntryIndex; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| 	struct Entry | template<class Type> | ||||||
| 	{ | struct HashTableEntry { | ||||||
| 	u64   Key; | 	u64   Key; | ||||||
| 	ssize Next; | 	ssize Next; | ||||||
| 	Type  Value; | 	Type  Value; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | // Forward declarations for all lifted functions | ||||||
|  | template<class Type> HashTable<Type>       hashtable_init(AllocatorInfo allocator); | ||||||
|  | template<class Type> HashTable<Type>       hashtable_init_reserve(AllocatorInfo allocator, usize num); | ||||||
|  | template<class Type> void                  clear(HashTable<Type>& table); | ||||||
|  | template<class Type> void                  destroy(HashTable<Type>& table); | ||||||
|  | template<class Type> Type*                 get(HashTable<Type>& table, u64 key); | ||||||
|  | template<class Type> void                  grow(HashTable<Type>& table); | ||||||
|  | template<class Type> void                  rehash(HashTable<Type>& table, ssize new_num); | ||||||
|  | template<class Type> void                  rehash_fast(HashTable<Type>& table); | ||||||
|  | template<class Type> void                  remove(HashTable<Type>& table, u64 key); | ||||||
|  | template<class Type> void                  remove_entry(HashTable<Type>& table, ssize idx); | ||||||
|  | template<class Type> void                  set(HashTable<Type>& table, u64 key, Type value); | ||||||
|  | template<class Type> ssize                 slot(HashTable<Type>& table, u64 key); | ||||||
|  | template<class Type> ssize                 add_entry(HashTable<Type>& table, u64 key); | ||||||
|  | template<class Type> HashTableFindResult   find(HashTable<Type>& table, u64 key); | ||||||
|  | template<class Type> bool                  full(HashTable<Type>& table); | ||||||
|  | template<class Type> void                  map(HashTable<Type>& table, void (*map_proc)(u64 key, Type value)); | ||||||
|  | template<class Type> void                  map_mut(HashTable<Type>& table, void (*map_proc)(u64 key, Type* value)); | ||||||
|  |  | ||||||
|  | template<typename Type> | ||||||
|  | struct HashTable | ||||||
|  | { | ||||||
| 	static constexpr f32 CriticalLoadScale = 0.7f; | 	static constexpr f32 CriticalLoadScale = 0.7f; | ||||||
|  |  | ||||||
| 	static | 	Array<ssize>              Hashes; | ||||||
| 	HashTable init( AllocatorInfo allocator ) | 	Array<HashTableEntry<Type>> Entries; | ||||||
| 	{ |  | ||||||
| 		HashTable<Type> result = init_reserve(allocator, 8); | #if 1 | ||||||
|  | #pragma region Member Mapping | ||||||
|  | 	forceinline static HashTable init(AllocatorInfo allocator)                  { return GEN_NS hashtable_init<Type>(allocator); } | ||||||
|  | 	forceinline static HashTable init_reserve(AllocatorInfo allocator, usize num) { return GEN_NS hashtable_init_reserve<Type>(allocator, num); } | ||||||
|  |  | ||||||
|  | 	forceinline void         clear()                           { GEN_NS clear<Type>(*this); } | ||||||
|  | 	forceinline void         destroy()                         { GEN_NS destroy<Type>(*this); } | ||||||
|  | 	forceinline Type*        get(u64 key)                      { return GEN_NS get<Type>(*this, key); } | ||||||
|  | 	forceinline void         grow()                            { GEN_NS grow<Type>(*this); } | ||||||
|  | 	forceinline void         rehash(ssize new_num)             { GEN_NS rehash<Type>(*this, new_num); } | ||||||
|  | 	forceinline void         rehash_fast()                     { GEN_NS rehash_fast<Type>(*this); } | ||||||
|  | 	forceinline void         remove(u64 key)                   { GEN_NS remove<Type>(*this, key); } | ||||||
|  | 	forceinline void         remove_entry(ssize idx)           { GEN_NS remove_entry<Type>(*this, idx); } | ||||||
|  | 	forceinline void         set(u64 key, Type value)          { GEN_NS set<Type>(*this, key, value); } | ||||||
|  | 	forceinline ssize        slot(u64 key)                     { return GEN_NS slot<Type>(*this, key); } | ||||||
|  | 	forceinline void         map(void (*proc)(u64, Type))      { GEN_NS map<Type>(*this, proc); } | ||||||
|  | 	forceinline void         map_mut(void (*proc)(u64, Type*)) { GEN_NS map_mut<Type>(*this, proc); } | ||||||
|  | #pragma endregion Member Mapping | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<typename Type> inline | ||||||
|  | HashTable<Type> hashtable_init(AllocatorInfo allocator) { | ||||||
|  | 	HashTable<Type> result = hashtable_init_reserve<Type>(allocator, 8); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	static | template<typename Type> inline | ||||||
| 	HashTable init_reserve( AllocatorInfo allocator, usize num ) | HashTable<Type> hashtable_init_reserve(AllocatorInfo allocator, usize num) | ||||||
| { | { | ||||||
| 	HashTable<Type> result = { { nullptr }, { nullptr } }; | 	HashTable<Type> result = { { nullptr }, { nullptr } }; | ||||||
|  |  | ||||||
| @@ -386,76 +416,70 @@ struct HashTable | |||||||
| 	result.Hashes.resize(num); | 	result.Hashes.resize(num); | ||||||
| 	result.Hashes.fill(0, num, -1); | 	result.Hashes.fill(0, num, -1); | ||||||
|  |  | ||||||
| 		result.Entries = Array<Entry>::init_reserve( allocator, num ); | 	result.Entries = Array<HashTableEntry<Type>>::init_reserve(allocator, num); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void clear( void ) | template<typename Type> inline | ||||||
| 	{ | void clear(HashTable<Type>& table) { | ||||||
| 		Entries.clear(); | 	table.Entries.clear(); | ||||||
| 		Hashes.fill( 0, Hashes.num(), -1); | 	table.Hashes.fill(0, table.Hashes.num(), -1); | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void destroy( void ) | template<typename Type> inline | ||||||
| 	{ | void destroy(HashTable<Type>& table) { | ||||||
| 		if ( Hashes && Hashes.get_header()->Capacity ) | 	if (table.Hashes && table.Hashes.get_header()->Capacity) { | ||||||
| 		{ | 		table.Hashes.free(); | ||||||
| 			Hashes.free(); | 		table.Entries.free(); | ||||||
| 			Entries.free(); |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| 	Type* get( u64 key ) | template<typename Type> inline | ||||||
| 	{ | Type* get(HashTable<Type>& table, u64 key) { | ||||||
| 		ssize idx = find( key ).EntryIndex; | 	ssize idx = find(table, key).EntryIndex; | ||||||
| 	if (idx >= 0) | 	if (idx >= 0) | ||||||
| 			return & Entries[ idx ].Value; | 		return &table.Entries[idx].Value; | ||||||
|  |  | ||||||
| 	return nullptr; | 	return nullptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	using MapProc = void (*)( u64 key, Type  value ); | template<typename Type> inline | ||||||
|  | void map(HashTable<Type>& table, void (*map_proc)(u64 key, Type value)) { | ||||||
| 	void map( MapProc map_proc ) |  | ||||||
| 	{ |  | ||||||
| 	GEN_ASSERT_NOT_NULL(map_proc); | 	GEN_ASSERT_NOT_NULL(map_proc); | ||||||
|  |  | ||||||
| 		for ( ssize idx = 0; idx < ssize(Entries.num()); ++idx ) | 	for (ssize idx = 0; idx < ssize(table.Entries.num()); ++idx) { | ||||||
| 		{ | 		map_proc(table.Entries[idx].Key, table.Entries[idx].Value); | ||||||
| 			map_proc( Entries[ idx ].Key, Entries[ idx ].Value ); |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| 	using MapMutProc = void (*)( u64 key, Type* value ); | template<typename Type> inline | ||||||
|  | void map_mut(HashTable<Type>& table, void (*map_proc)(u64 key, Type* value)) { | ||||||
| 	void map_mut( MapMutProc map_proc ) |  | ||||||
| 	{ |  | ||||||
| 	GEN_ASSERT_NOT_NULL(map_proc); | 	GEN_ASSERT_NOT_NULL(map_proc); | ||||||
|  |  | ||||||
| 		for ( ssize idx = 0; idx < ssize(Entries.num()); ++idx ) | 	for (ssize idx = 0; idx < ssize(table.Entries.num()); ++idx) { | ||||||
| 		{ | 		map_proc(table.Entries[idx].Key, &table.Entries[idx].Value); | ||||||
| 			map_proc( Entries[ idx ].Key, & Entries[ idx ].Value ); |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void grow() | template<typename Type> inline | ||||||
| 	{ | void grow(HashTable<Type>& table) { | ||||||
| 		ssize new_num = Array<Entry>::grow_formula( Entries.num() ); | 	ssize new_num = Array<HashTableEntry<Type>>::grow_formula(table.Entries.num()); | ||||||
| 		rehash( new_num ); | 	rehash(table, new_num); | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void rehash( ssize new_num ) | template<typename Type> inline | ||||||
|  | void rehash(HashTable<Type>& table, ssize new_num) | ||||||
| { | { | ||||||
| 	ssize last_added_index; | 	ssize last_added_index; | ||||||
|  | 	HashTable<Type> new_ht = hashtable_init_reserve<Type>(table.Hashes.get_header()->Allocator, new_num); | ||||||
|  |  | ||||||
| 		HashTable<Type> new_ht = init_reserve( Hashes.get_header()->Allocator, new_num ); | 	for (ssize idx = 0; idx < ssize(table.Entries.num()); ++idx) | ||||||
| 		for ( ssize idx = 0; idx < ssize(Entries.num()); ++idx ) |  | ||||||
| 	{ | 	{ | ||||||
| 			FindResult find_result; | 		HashTableFindResult find_result; | ||||||
|  | 		HashTableEntry<Type>& entry = table.Entries[idx]; | ||||||
|  |  | ||||||
| 			Entry& entry     = Entries[ idx ]; | 		find_result = find(new_ht, entry.Key); | ||||||
| 			find_result      = new_ht.find( entry.Key ); | 		last_added_index = add_entry(new_ht, entry.Key); | ||||||
| 			last_added_index = new_ht.add_entry( entry.Key ); |  | ||||||
|  |  | ||||||
| 		if (find_result.PrevIndex < 0) | 		if (find_result.PrevIndex < 0) | ||||||
| 			new_ht.Hashes[find_result.HashIndex] = last_added_index; | 			new_ht.Hashes[find_result.HashIndex] = last_added_index; | ||||||
| @@ -466,136 +490,130 @@ struct HashTable | |||||||
| 		new_ht.Entries[last_added_index].Value = entry.Value; | 		new_ht.Entries[last_added_index].Value = entry.Value; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 		destroy(); | 	destroy(table); | ||||||
| 		*this = new_ht; | 	table = new_ht; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void rehash_fast() | template<typename Type> inline | ||||||
|  | void rehash_fast(HashTable<Type>& table) | ||||||
| { | { | ||||||
| 	ssize idx; | 	ssize idx; | ||||||
|  |  | ||||||
| 		for ( idx = 0; idx < ssize(Entries.num()); idx++ ) | 	for (idx = 0; idx < ssize(table.Entries.num()); idx++) | ||||||
| 			Entries[ idx ].Next = -1; | 		table.Entries[idx].Next = -1; | ||||||
|  |  | ||||||
| 		for ( idx = 0; idx < ssize(Hashes.num()); idx++ ) | 	for (idx = 0; idx < ssize(table.Hashes.num()); idx++) | ||||||
| 			Hashes[ idx ] = -1; | 		table.Hashes[idx] = -1; | ||||||
|  |  | ||||||
| 		for ( idx = 0; idx < ssize(Entries.num()); idx++ ) | 	for (idx = 0; idx < ssize(table.Entries.num()); idx++) | ||||||
| 	{ | 	{ | ||||||
| 			Entry*     entry; | 		HashTableEntry<Type>* entry; | ||||||
| 			FindResult find_result; | 		HashTableFindResult find_result; | ||||||
|  |  | ||||||
| 			entry       = & Entries[ idx ]; | 		entry = &table.Entries[idx]; | ||||||
| 			find_result = find( entry->Key ); | 		find_result = find(table, entry->Key); | ||||||
|  |  | ||||||
| 		if (find_result.PrevIndex < 0) | 		if (find_result.PrevIndex < 0) | ||||||
| 				Hashes[ find_result.HashIndex ] = idx; | 			table.Hashes[find_result.HashIndex] = idx; | ||||||
| 		else | 		else | ||||||
| 				Entries[ find_result.PrevIndex ].Next = idx; | 			table.Entries[find_result.PrevIndex].Next = idx; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void remove( u64 key ) | template<typename Type> inline | ||||||
| 	{ | void remove(HashTable<Type>& table, u64 key) { | ||||||
| 		FindResult find_result = find( key); | 	HashTableFindResult find_result = find(table, key); | ||||||
|  |  | ||||||
| 		if ( find_result.EntryIndex >= 0 ) | 	if (find_result.EntryIndex >= 0) { | ||||||
| 		{ | 		table.Entries.remove_at(find_result.EntryIndex); | ||||||
| 			Entries.remove_at( find_result.EntryIndex ); | 		rehash_fast(table); | ||||||
| 			rehash_fast(); |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void remove_entry( ssize idx ) | template<typename Type> inline | ||||||
| 	{ | void remove_entry(HashTable<Type>& table, ssize idx) { | ||||||
| 		Entries.remove_at( idx ); | 	table.Entries.remove_at(idx); | ||||||
| } | } | ||||||
|  |  | ||||||
| 	void set( u64 key, Type value ) | template<typename Type> inline | ||||||
|  | void set(HashTable<Type>& table, u64 key, Type value) | ||||||
| { | { | ||||||
| 	ssize idx; | 	ssize idx; | ||||||
| 		FindResult find_result; | 	HashTableFindResult find_result; | ||||||
|  |  | ||||||
| 		if ( full() ) | 	if (full(table)) | ||||||
| 			grow(); | 		grow(table); | ||||||
|  |  | ||||||
| 		find_result = find( key ); | 	find_result = find(table, key); | ||||||
| 		if ( find_result.EntryIndex >= 0 ) | 	if (find_result.EntryIndex >= 0) { | ||||||
| 		{ |  | ||||||
| 		idx = find_result.EntryIndex; | 		idx = find_result.EntryIndex; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 			idx = add_entry( key ); | 		idx = add_entry(table, key); | ||||||
|  |  | ||||||
| 			if ( find_result.PrevIndex >= 0 ) | 		if (find_result.PrevIndex >= 0) { | ||||||
| 			{ | 			table.Entries[find_result.PrevIndex].Next = idx; | ||||||
| 				Entries[ find_result.PrevIndex ].Next = idx; |  | ||||||
| 		} | 		} | ||||||
| 			else | 		else { | ||||||
| 			{ | 			table.Hashes[find_result.HashIndex] = idx; | ||||||
| 				Hashes[ find_result.HashIndex ] = idx; |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 		Entries[ idx ].Value = value; | 	table.Entries[idx].Value = value; | ||||||
|  |  | ||||||
| 		if ( full() ) | 	if (full(table)) | ||||||
| 			grow(); | 		grow(table); | ||||||
| } | } | ||||||
|  |  | ||||||
| 	ssize slot( u64 key ) | template<typename Type> inline | ||||||
| 	{ | ssize slot(HashTable<Type>& table, u64 key) { | ||||||
| 		for ( ssize idx = 0; idx < ssize(Hashes.num()); ++idx ) | 	for (ssize idx = 0; idx < ssize(table.Hashes.num()); ++idx) | ||||||
| 			if ( Hashes[ idx ] == key ) | 		if (table.Hashes[idx] == key) | ||||||
| 			return idx; | 			return idx; | ||||||
|  |  | ||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	Array< ssize>    Hashes; | template<typename Type> inline | ||||||
| 	Array< Entry> Entries; | ssize add_entry(HashTable<Type>& table, u64 key) { | ||||||
|  |  | ||||||
| protected: |  | ||||||
|  |  | ||||||
| 	ssize add_entry( u64 key ) |  | ||||||
| 	{ |  | ||||||
| 	ssize idx; | 	ssize idx; | ||||||
| 		Entry entry = { key, -1 }; | 	HashTableEntry<Type> entry = { key, -1 }; | ||||||
|  |  | ||||||
| 		idx = Entries.num(); | 	idx = table.Entries.num(); | ||||||
| 		Entries.append( entry ); | 	table.Entries.append(entry); | ||||||
| 	return idx; | 	return idx; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	FindResult find( u64 key ) | template<typename Type> inline | ||||||
|  | HashTableFindResult find(HashTable<Type>& table, u64 key) | ||||||
| { | { | ||||||
| 		FindResult result = { -1, -1, -1 }; | 	HashTableFindResult result = { -1, -1, -1 }; | ||||||
|  |  | ||||||
| 		if ( Hashes.num() > 0 ) | 	if (table.Hashes.num() > 0) | ||||||
| 	{ | 	{ | ||||||
| 			result.HashIndex    = key % Hashes.num(); | 		result.HashIndex = key % table.Hashes.num(); | ||||||
| 			result.EntryIndex  = Hashes[ result.HashIndex ]; | 		result.EntryIndex = table.Hashes[result.HashIndex]; | ||||||
|  |  | ||||||
| 		while (result.EntryIndex >= 0) | 		while (result.EntryIndex >= 0) | ||||||
| 		{ | 		{ | ||||||
| 				if ( Entries[ result.EntryIndex ].Key == key ) | 			if (table.Entries[result.EntryIndex].Key == key) | ||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
| 			result.PrevIndex = result.EntryIndex; | 			result.PrevIndex = result.EntryIndex; | ||||||
| 				result.EntryIndex = Entries[ result.EntryIndex ].Next; | 			result.EntryIndex = table.Entries[result.EntryIndex].Next; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| 	b32 full() | template<typename Type> inline | ||||||
| 	{ | bool full(HashTable<Type>& table) { | ||||||
| 		usize critical_load = usize( CriticalLoadScale * f32(Hashes.num()) ); | 	usize critical_load = usize(HashTable<Type>::CriticalLoadScale * f32(table.Hashes.num())); | ||||||
| 		b32 result = Entries.num() > critical_load; | 	b32 result = table.Entries.num() > critical_load; | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| }; | #pragma endregion HashTable | ||||||
|  |  | ||||||
| #pragma endregion Containers | #pragma endregion Containers | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user