Pārlūkot izejas kodu

core: use HashMap everywhere

Daniele Bartolini 6 gadi atpakaļ
vecāks
revīzija
cfad7037b9

+ 10 - 0
src/core/containers/hash_map.h

@@ -30,6 +30,10 @@ namespace hash_map
 	/// the key does not exist in the map.
 	template <typename TKey, typename TValue, typename Hash, typename KeyEqual> const TValue& get(const HashMap<TKey, TValue, Hash, KeyEqual>& m, const TKey& key, const TValue& deffault);
 
+	/// Returns the value for the given @a key or @a deffault if
+	/// the key does not exist in the map.
+	template <typename TKey, typename TValue, typename Hash, typename KeyEqual> TValue& get(HashMap<TKey, TValue, Hash, KeyEqual>& m, const TKey& key, const TValue& deffault);
+
 	/// Sets the @a value for the @a key in the map.
 	template <typename TKey, typename TValue, typename Hash, typename KeyEqual> void set(HashMap<TKey, TValue, Hash, KeyEqual>& m, const TKey& key, const TValue& value);
 
@@ -236,6 +240,12 @@ namespace hash_map
 			return m._data[i].second;
 	}
 
+	template <typename TKey, typename TValue, typename Hash, typename KeyEqual>
+	TValue& get(HashMap<TKey, TValue, Hash, KeyEqual>& m, const TKey& key, const TValue& deffault)
+	{
+		return const_cast<TValue&>(hash_map::get((const HashMap<TKey, TValue, Hash, KeyEqual>&)m, key, deffault));
+	}
+
 	template <typename TKey, typename TValue, typename Hash, typename KeyEqual>
 	void set(HashMap<TKey, TValue, Hash, KeyEqual>& m, const TKey& key, const TValue& value)
 	{

+ 0 - 209
src/core/containers/sort_map.h

@@ -1,209 +0,0 @@
-/*
- * Copyright (c) 2012-2018 Daniele Bartolini and individual contributors.
- * License: https://github.com/dbartolini/crown/blob/master/LICENSE
- */
-
-#pragma once
-
-#include "core/containers/vector.h"
-#include <algorithm>
-
-namespace crown
-{
-/// Functions to manipulate SortMap.
-///
-/// @ingroup Containers
-namespace sort_map
-{
-	/// Returns the number of items in the map @a m.
-	template <typename TKey, typename TValue, typename Compare> u32 size(const SortMap<TKey, TValue, Compare>& m);
-
-	/// Returns whether the @a key exists in the map.
-	template <typename TKey, typename TValue, typename Compare> bool has(const SortMap<TKey, TValue, Compare>& m, const TKey& key);
-
-	/// Returns the value for the given @a key or @a deffault if
-	/// the key does not exist in the map.
-	template <typename TKey, typename TValue, typename Compare> const TValue& get(const SortMap<TKey, TValue, Compare>& m, const TKey& key, const TValue& deffault);
-
-	/// Returns the value for the given @a key or @a deffault if
-	/// the key does not exist in the map.
-	template <typename TKey, typename TValue, typename Compare> TValue& get(SortMap<TKey, TValue, Compare>& m, const TKey& key, const TValue& deffault);
-
-	/// Sorts the keys in the map.
-	template <typename TKey, typename TValue, typename Compare> void sort(SortMap<TKey, TValue, Compare>& m);
-
-	template <typename TKey, typename TValue, typename Compare> void set(SortMap<TKey, TValue, Compare>& m, const TKey& key, const TValue& val);
-
-	/// Removes the @a key from the map if it exists.
-	template <typename TKey, typename TValue, typename Compare> void remove(SortMap<TKey, TValue, Compare>& m, const TKey& key);
-
-	/// Removes all the items in the map.
-	template <typename TKey, typename TValue, typename Compare> void clear(SortMap<TKey, TValue, Compare>& m);
-
-	/// Returns a pointer to the first item in the map, can be used to
-	/// efficiently iterate over the elements.
-	template <typename TKey, typename TValue, typename Compare> const typename SortMap<TKey, TValue, Compare>::Entry* begin(const SortMap<TKey, TValue, Compare>& m);
-	template <typename TKey, typename TValue, typename Compare> const typename SortMap<TKey, TValue, Compare>::Entry* end(const SortMap<TKey, TValue, Compare>& m);
-
-} // namespace sort_map
-
-namespace sort_map_internal
-{
-	const u32 END_OF_LIST = 0xffffffffu;
-
-	struct FindResult
-	{
-		u32 item_i;
-	};
-
-	template <typename TKey, typename TValue, typename Compare>
-	struct CompareEntry
-	{
-		bool operator()(const typename SortMap<TKey, TValue, Compare>::Entry& a,
-			const typename SortMap<TKey, TValue, Compare>::Entry& b) const
-		{
-			return comp(a.first, b.first);
-		}
-
-		bool operator()(const typename SortMap<TKey, TValue, Compare>::Entry& a,
-			const TKey& key) const
-		{
-			return comp(a.first, key);
-		}
-
-		Compare comp;
-	};
-
-	template <typename TKey, typename TValue, typename Compare>
-	inline FindResult find(const SortMap<TKey, TValue, Compare>& m, const TKey& key)
-	{
-		CE_ASSERT(m._is_sorted, "Map not sorted");
-
-		FindResult result;
-		result.item_i = END_OF_LIST;
-
-		const typename SortMap<TKey, TValue, Compare>::Entry* first =
-			std::lower_bound(vector::begin(m._data), vector::end(m._data), key,
-			sort_map_internal::CompareEntry<TKey, TValue, Compare>());
-
-		if (first != vector::end(m._data) && !(key < first->first))
-			result.item_i = u32(first - vector::begin(m._data));
-
-		return result;
-	}
-
-} // namespace sort_map_internal
-
-namespace sort_map
-{
-	template <typename TKey, typename TValue, typename Compare>
-	inline u32 size(const SortMap<TKey, TValue, Compare>& m)
-	{
-		return vector::size(m._data);
-	}
-
-	template <typename TKey, typename TValue, typename Compare>
-	inline bool has(const SortMap<TKey, TValue, Compare>& m, const TKey& key)
-	{
-		return sort_map_internal::find(m, key).item_i != sort_map_internal::END_OF_LIST;
-	}
-
-	template <typename TKey, typename TValue, typename Compare>
-	const TValue& get(const SortMap<TKey, TValue, Compare>& m, const TKey& key, const TValue& deffault)
-	{
-		sort_map_internal::FindResult result = sort_map_internal::find(m, key);
-
-		if (result.item_i == sort_map_internal::END_OF_LIST)
-			return deffault;
-
-		return m._data[result.item_i].second;
-	}
-
-	template <typename TKey, typename TValue, typename Compare>
-	TValue& get(SortMap<TKey, TValue, Compare>& m, const TKey& key, const TValue& deffault)
-	{
-		return const_cast<TValue&>(get(static_cast<const SortMap<TKey, TValue, Compare>&>(m), key, deffault));
-	}
-
-	template <typename TKey, typename TValue, typename Compare>
-	inline void sort(SortMap<TKey, TValue, Compare>& m)
-	{
-		std::sort(vector::begin(m._data), vector::end(m._data),
-			sort_map_internal::CompareEntry<TKey, TValue, Compare>());
-#if CROWN_DEBUG
-		m._is_sorted = true;
-#endif // CROWN_DEBUG
-	}
-
-	template <typename TKey, typename TValue, typename Compare>
-	inline void set(SortMap<TKey, TValue, Compare>& m, const TKey& key, const TValue& val)
-	{
-		sort_map_internal::FindResult result = sort_map_internal::find(m, key);
-
-		if (result.item_i == sort_map_internal::END_OF_LIST)
-		{
-			typename SortMap<TKey, TValue, Compare>::Entry e(*m._data._allocator);
-			e.first = key;
-			e.second = val;
-			vector::push_back(m._data, e);
-		}
-		else
-		{
-			m._data[result.item_i].second = val;
-		}
-#if CROWN_DEBUG
-		m._is_sorted = false;
-#endif // CROWN_DEBUG
-	}
-
-	template <typename TKey, typename TValue, typename Compare>
-	inline void remove(SortMap<TKey, TValue, Compare>& m, const TKey& key)
-	{
-		sort_map_internal::FindResult result = sort_map_internal::find(m, key);
-
-		if (result.item_i == sort_map_internal::END_OF_LIST)
-			return;
-
-		if (vector::size(m._data))
-		{
-			m._data[result.item_i] = m._data[vector::size(m._data) - 1];
-			vector::pop_back(m._data);
-		}
-#if CROWN_DEBUG
-		m._is_sorted = false;
-#endif // CROWN_DEBUG
-	}
-
-	template <typename TKey, typename TValue, typename Compare>
-	inline void clear(SortMap<TKey, TValue, Compare>& m)
-	{
-		vector::clear(m._data);
-#if CROWN_DEBUG
-		m._is_sorted = true;
-#endif // CROWN_DEBUG
-	}
-
-	template <typename TKey, typename TValue, typename Compare>
-	inline const typename SortMap<TKey, TValue, Compare>::Entry* begin(const SortMap<TKey, TValue, Compare>& m)
-	{
-		return vector::begin(m._data);
-	}
-
-	template <typename TKey, typename TValue, typename Compare>
-	inline const typename SortMap<TKey, TValue, Compare>::Entry* end(const SortMap<TKey, TValue, Compare>& m)
-	{
-		return vector::end(m._data);
-	}
-
-} // namespace sort_map
-
-template <typename TKey, typename TValue, typename Compare>
-inline SortMap<TKey, TValue, Compare>::SortMap(Allocator& a)
-	: _data(a)
-#if CROWN_DEBUG
-	, _is_sorted(true)
-#endif // CROWN_DEBUG
-{
-}
-
-} // namespace crown

+ 0 - 22
src/core/containers/types.h

@@ -141,26 +141,4 @@ struct HashSet
 	HashSet<TKey, Hash, KeyEqual>& operator=(const HashSet<TKey, Hash, KeyEqual>& other);
 };
 
-/// Vector of sorted items.
-///
-/// @note
-/// Items are not automatically sorted, you have to call sort_map::sort()
-/// whenever you are done inserting/removing items.
-///
-/// @ingroup Containers.
-template <typename TKey, typename TValue, typename Compare = less<TKey> >
-struct SortMap
-{
-	ALLOCATOR_AWARE;
-
-	typedef PAIR(TKey, TValue) Entry;
-
-	Vector<Entry> _data;
-#if CROWN_DEBUG
-	bool _is_sorted;
-#endif
-
-	SortMap(Allocator& a);
-};
-
 } // namespace crown

+ 29 - 20
src/resource/resource_manager.cpp

@@ -4,7 +4,7 @@
  */
 
 #include "core/containers/array.h"
-#include "core/containers/sort_map.h"
+#include "core/containers/hash_map.h"
 #include "core/memory/temp_allocator.h"
 #include "core/strings/dynamic_string.h"
 #include "resource/resource_loader.h"
@@ -14,6 +14,15 @@ namespace crown
 {
 const ResourceManager::ResourceEntry ResourceManager::ResourceEntry::NOT_FOUND = { 0xffffffffu, NULL };
 
+template<>
+struct hash<ResourceManager::ResourcePair>
+{
+	u32 operator()(const ResourceManager::ResourcePair& val) const
+	{
+		return u32(val.type._id ^ val.name._id);
+	}
+};
+
 ResourceManager::ResourceManager(ResourceLoader& rl)
 	: _resource_heap(default_allocator(), "resource")
 	, _loader(&rl)
@@ -25,10 +34,13 @@ ResourceManager::ResourceManager(ResourceLoader& rl)
 
 ResourceManager::~ResourceManager()
 {
-	auto cur = sort_map::begin(_rm);
-	auto end = sort_map::end(_rm);
+	auto cur = hash_map::begin(_rm);
+	auto end = hash_map::end(_rm);
 	for (; cur != end; ++cur)
 	{
+		if (hash_map::is_hole(_rm, cur))
+			continue;
+
 		const StringId64 type = cur->first.type;
 		const StringId64 name = cur->first.name;
 		on_offline(type, name);
@@ -39,7 +51,7 @@ ResourceManager::~ResourceManager()
 void ResourceManager::load(StringId64 type, StringId64 name)
 {
 	ResourcePair id = { type, name };
-	ResourceEntry& entry = sort_map::get(_rm, id, ResourceEntry::NOT_FOUND);
+	ResourceEntry& entry = hash_map::get(_rm, id, ResourceEntry::NOT_FOUND);
 
 	if (entry == ResourceEntry::NOT_FOUND)
 	{
@@ -49,7 +61,7 @@ void ResourceManager::load(StringId64 type, StringId64 name)
 		rtd.online = NULL;
 		rtd.offline = NULL;
 		rtd.unload = NULL;
-		rtd = sort_map::get(_type_data, type, rtd);
+		rtd = hash_map::get(_type_data, type, rtd);
 
 		ResourceRequest rr;
 		rr.type = type;
@@ -71,36 +83,35 @@ void ResourceManager::unload(StringId64 type, StringId64 name)
 	flush();
 
 	ResourcePair id = { type, name };
-	ResourceEntry& entry = sort_map::get(_rm, id, ResourceEntry::NOT_FOUND);
+	ResourceEntry& entry = hash_map::get(_rm, id, ResourceEntry::NOT_FOUND);
 
 	if (--entry.references == 0)
 	{
 		on_offline(type, name);
 		on_unload(type, entry.data);
 
-		sort_map::remove(_rm, id);
-		sort_map::sort(_rm);
+		hash_map::remove(_rm, id);
 	}
 }
 
 void ResourceManager::reload(StringId64 type, StringId64 name)
 {
 	const ResourcePair id = { type, name };
-	const ResourceEntry& entry = sort_map::get(_rm, id, ResourceEntry::NOT_FOUND);
+	const ResourceEntry& entry = hash_map::get(_rm, id, ResourceEntry::NOT_FOUND);
 	const u32 old_refs = entry.references;
 
 	unload(type, name);
 	load(type, name);
 	flush();
 
-	ResourceEntry& new_entry = sort_map::get(_rm, id, ResourceEntry::NOT_FOUND);
+	ResourceEntry& new_entry = hash_map::get(_rm, id, ResourceEntry::NOT_FOUND);
 	new_entry.references = old_refs;
 }
 
 bool ResourceManager::can_get(StringId64 type, StringId64 name)
 {
 	const ResourcePair id = { type, name };
-	return _autoload ? true : sort_map::has(_rm, id);
+	return _autoload ? true : hash_map::has(_rm, id);
 }
 
 const void* ResourceManager::get(StringId64 type, StringId64 name)
@@ -116,13 +127,13 @@ const void* ResourceManager::get(StringId64 type, StringId64 name)
 
 	CE_ASSERT(can_get(type, name), "Resource not loaded #ID(%s)", path.c_str());
 
-	if (_autoload && !sort_map::has(_rm, id))
+	if (_autoload && !hash_map::has(_rm, id))
 	{
 		load(type, name);
 		flush();
 	}
 
-	const ResourceEntry& entry = sort_map::get(_rm, id, ResourceEntry::NOT_FOUND);
+	const ResourceEntry& entry = hash_map::get(_rm, id, ResourceEntry::NOT_FOUND);
 	return entry.data;
 }
 
@@ -155,8 +166,7 @@ void ResourceManager::complete_request(StringId64 type, StringId64 name, void* d
 
 	ResourcePair id = { type, name };
 
-	sort_map::set(_rm, id, entry);
-	sort_map::sort(_rm);
+	hash_map::set(_rm, id, entry);
 
 	on_online(type, name);
 }
@@ -170,13 +180,12 @@ void ResourceManager::register_type(StringId64 type, u32 version, LoadFunction l
 	rtd.offline = offline;
 	rtd.unload = unload;
 
-	sort_map::set(_type_data, type, rtd);
-	sort_map::sort(_type_data);
+	hash_map::set(_type_data, type, rtd);
 }
 
 void ResourceManager::on_online(StringId64 type, StringId64 name)
 {
-	OnlineFunction func = sort_map::get(_type_data, type, ResourceTypeData()).online;
+	OnlineFunction func = hash_map::get(_type_data, type, ResourceTypeData()).online;
 
 	if (func)
 		func(name, *this);
@@ -184,7 +193,7 @@ void ResourceManager::on_online(StringId64 type, StringId64 name)
 
 void ResourceManager::on_offline(StringId64 type, StringId64 name)
 {
-	OfflineFunction func = sort_map::get(_type_data, type, ResourceTypeData()).offline;
+	OfflineFunction func = hash_map::get(_type_data, type, ResourceTypeData()).offline;
 
 	if (func)
 		func(name, *this);
@@ -192,7 +201,7 @@ void ResourceManager::on_offline(StringId64 type, StringId64 name)
 
 void ResourceManager::on_unload(StringId64 type, void* data)
 {
-	UnloadFunction func = sort_map::get(_type_data, type, ResourceTypeData()).unload;
+	UnloadFunction func = hash_map::get(_type_data, type, ResourceTypeData()).unload;
 
 	if (func)
 		func(_resource_heap, data);

+ 7 - 2
src/resource/resource_manager.h

@@ -33,6 +33,11 @@ struct ResourceManager
 		{
 			return type < a.type || (type == a.type && name < a.name);
 		}
+
+		bool operator==(const ResourcePair& a) const
+		{
+			return type == a.type && name == a.name;
+		}
 	};
 
 	struct ResourceEntry
@@ -57,8 +62,8 @@ struct ResourceManager
 		UnloadFunction unload;
 	};
 
-	typedef SortMap<StringId64, ResourceTypeData> TypeMap;
-	typedef SortMap<ResourcePair, ResourceEntry> ResourceMap;
+	typedef HashMap<StringId64, ResourceTypeData> TypeMap;
+	typedef HashMap<ResourcePair, ResourceEntry> ResourceMap;
 
 	ProxyAllocator _resource_heap;
 	ResourceLoader* _loader;

+ 12 - 9
src/resource/unit_compiler.cpp

@@ -4,7 +4,7 @@
  */
 
 #include "core/containers/array.h"
-#include "core/containers/sort_map.h"
+#include "core/containers/hash_map.h"
 #include "core/json/json_object.h"
 #include "core/json/sjson.h"
 #include "core/math/math.h"
@@ -15,6 +15,7 @@
 #include "resource/unit_compiler.h"
 #include "resource/unit_resource.h"
 #include "world/types.h"
+#include <algorithm>
 
 namespace crown
 {
@@ -409,10 +410,13 @@ Buffer UnitCompiler::blob()
 	ur.num_units = _num_units;
 	ur.num_component_types = 0;
 
-	auto cur = sort_map::begin(_component_data);
-	auto end = sort_map::end(_component_data);
+	auto cur = hash_map::begin(_component_data);
+	auto end = hash_map::end(_component_data);
 	for (; cur != end; ++cur)
 	{
+		if (hash_map::is_hole(_component_data, cur))
+			continue;
+
 		const u32 num = cur->second._num;
 
 		if (num > 0)
@@ -425,7 +429,7 @@ Buffer UnitCompiler::blob()
 	for (u32 i = 0; i < array::size(_component_info); ++i)
 	{
 		const StringId32 type        = _component_info[i]._type;
-		const ComponentTypeData& ctd = sort_map::get(_component_data, type, ComponentTypeData(default_allocator()));
+		const ComponentTypeData& ctd = hash_map::get(_component_data, type, ComponentTypeData(default_allocator()));
 
 		const Buffer& data           = ctd._data;
 		const Array<u32>& unit_index = ctd._unit_index;
@@ -456,7 +460,7 @@ Buffer UnitCompiler::blob()
 
 void UnitCompiler::add_component_data(StringId32 type, const Buffer& data, u32 unit_index)
 {
-	ComponentTypeData& ctd = const_cast<ComponentTypeData&>(sort_map::get(_component_data, type, ComponentTypeData(default_allocator())));
+	ComponentTypeData& ctd = const_cast<ComponentTypeData&>(hash_map::get(_component_data, type, ComponentTypeData(default_allocator())));
 
 	array::push(ctd._data, array::begin(data), array::size(data));
 	array::push_back(ctd._unit_index, unit_index);
@@ -477,8 +481,7 @@ void UnitCompiler::register_component_compiler(StringId32 type, CompileFunction
 	cti._type = type;
 	cti._spawn_order = spawn_order;
 
-	sort_map::set(_component_data, type, ctd);
-	sort_map::sort(_component_data);
+	hash_map::set(_component_data, type, ctd);
 
 	array::push_back(_component_info, cti);
 	std::sort(array::begin(_component_info), array::end(_component_info));
@@ -486,9 +489,9 @@ void UnitCompiler::register_component_compiler(StringId32 type, CompileFunction
 
 Buffer UnitCompiler::compile_component(StringId32 type, const char* json)
 {
-	DATA_COMPILER_ASSERT(sort_map::has(_component_data, type), _opts, "Unknown component");
+	DATA_COMPILER_ASSERT(hash_map::has(_component_data, type), _opts, "Unknown component");
 
-	return sort_map::get(_component_data, type, ComponentTypeData(default_allocator()))._compiler(json, _opts);
+	return hash_map::get(_component_data, type, ComponentTypeData(default_allocator()))._compiler(json, _opts);
 }
 
 } // namespace crown

+ 1 - 1
src/resource/unit_compiler.h

@@ -45,7 +45,7 @@ struct UnitCompiler
 		}
 	};
 
-	typedef SortMap<StringId32, ComponentTypeData> ComponentTypeMap;
+	typedef HashMap<StringId32, ComponentTypeData> ComponentTypeMap;
 	typedef Array<ComponentTypeInfo> ComponentTypeArray;
 
 	CompileOptions& _opts;

+ 0 - 1
src/resource/unit_resource.cpp

@@ -4,7 +4,6 @@
  */
 
 #include "core/containers/array.h"
-#include "core/containers/sort_map.h"
 #include "core/filesystem/file.h"
 #include "core/filesystem/filesystem.h"
 #include "core/memory/allocator.h"

+ 12 - 11
src/world/material_manager.cpp

@@ -3,7 +3,7 @@
  * License: https://github.com/dbartolini/crown/blob/master/LICENSE
  */
 
-#include "core/containers/sort_map.h"
+#include "core/containers/hash_map.h"
 #include "core/filesystem/file.h"
 #include "resource/material_resource.h"
 #include "resource/resource_manager.h"
@@ -22,10 +22,13 @@ MaterialManager::MaterialManager(Allocator& a, ResourceManager& rm)
 
 MaterialManager::~MaterialManager()
 {
-	auto cur = sort_map::begin(_materials);
-	auto end = sort_map::end(_materials);
+	auto cur = hash_map::begin(_materials);
+	auto end = hash_map::end(_materials);
 	for (; cur != end; ++cur)
 	{
+		if (hash_map::is_hole(_materials, cur))
+			continue;
+
 		_allocator->deallocate(cur->second);
 	}
 }
@@ -94,7 +97,7 @@ void MaterialManager::unload(Allocator& a, void* res)
 
 void MaterialManager::create_material(StringId64 id)
 {
-	if (sort_map::has(_materials, id))
+	if (hash_map::has(_materials, id))
 		return;
 
 	const MaterialResource* mr = (MaterialResource*)_resource_manager->get(RESOURCE_TYPE_MATERIAL, id);
@@ -107,23 +110,21 @@ void MaterialManager::create_material(StringId64 id)
 	const char* data = (char*)mr + mr->dynamic_data_offset;
 	memcpy(mat->_data, data, mr->dynamic_data_size);
 
-	sort_map::set(_materials, id, mat);
-	sort_map::sort(_materials);
+	hash_map::set(_materials, id, mat);
 }
 
 void MaterialManager::destroy_material(StringId64 id)
 {
-	Material* mat = sort_map::get(_materials, id, (Material*)NULL);
+	Material* mat = hash_map::get(_materials, id, (Material*)NULL);
 	_allocator->deallocate(mat);
 
-	sort_map::remove(_materials, id);
-	sort_map::sort(_materials);
+	hash_map::remove(_materials, id);
 }
 
 Material* MaterialManager::get(StringId64 id)
 {
-	CE_ASSERT(sort_map::has(_materials, id), "Material not found");
-	return sort_map::get(_materials, id, (Material*)NULL);
+	CE_ASSERT(hash_map::has(_materials, id), "Material not found");
+	return hash_map::get(_materials, id, (Material*)NULL);
 }
 
 } // namespace crown

+ 1 - 1
src/world/material_manager.h

@@ -18,7 +18,7 @@ struct MaterialManager
 {
 	Allocator* _allocator;
 	ResourceManager* _resource_manager;
-	SortMap<StringId64, Material*> _materials;
+	HashMap<StringId64, Material*> _materials;
 
 	///
 	MaterialManager(Allocator& a, ResourceManager& rm);