Sfoglia il codice sorgente

core: use HashMap as backing storage for JsonObject

Daniele Bartolini 6 anni fa
parent
commit
63edec728d

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

@@ -42,6 +42,17 @@ namespace hash_map
 	/// Calls destructor on the items.
 	template <typename TKey, typename TValue, typename Hash, typename KeyEqual> void clear(HashMap<TKey, TValue, Hash, KeyEqual>& m);
 
+	/// Returns whether the @a entry in the map @a m contains data or is a hole.
+	/// If the entry is a hole you should not touch data in the entry.
+	template <typename TKey, typename TValue, typename Hash, typename KeyEqual> bool is_hole(const HashMap<TKey, TValue, Hash, KeyEqual>& m, const typename HashMap<TKey, TValue, Hash, KeyEqual>::Entry* entry);
+
+	/// Returns a pointer to the first item in the map, can be used to
+	/// efficiently iterate over the elements (in random order).
+	/// @note
+	/// You should check whether the item is valid with hash_map::is_hole().
+	template <typename TKey, typename TValue, typename Hash, typename KeyEqual> const typename HashMap<TKey, TValue, Hash, KeyEqual>::Entry* begin(const HashMap<TKey, TValue, Hash, KeyEqual>& m);
+	template <typename TKey, typename TValue, typename Hash, typename KeyEqual> const typename HashMap<TKey, TValue, Hash, KeyEqual>::Entry* end(const HashMap<TKey, TValue, Hash, KeyEqual>& m);
+
 } // namespace hash_map
 
 namespace hash_map_internal
@@ -271,6 +282,27 @@ namespace hash_map
 		m._size = 0;
 	}
 
+	template <typename TKey, typename TValue, typename Hash, typename KeyEqual>
+	bool is_hole(const HashMap<TKey, TValue, Hash, KeyEqual>& m, const typename HashMap<TKey, TValue, Hash, KeyEqual>::Entry* entry)
+	{
+		const u32 ii = u32(entry - m._data);
+		const u32 index = m._index[ii].index;
+
+		return index == hash_map_internal::FREE || hash_map_internal::is_deleted(index);
+	}
+
+	template <typename TKey, typename TValue, typename Hash, typename KeyEqual>
+	const typename HashMap<TKey, TValue, Hash, KeyEqual>::Entry* begin(const HashMap<TKey, TValue, Hash, KeyEqual>& m)
+	{
+		return m._data;
+	}
+
+	template <typename TKey, typename TValue, typename Hash, typename KeyEqual>
+	const typename HashMap<TKey, TValue, Hash, KeyEqual>::Entry* end(const HashMap<TKey, TValue, Hash, KeyEqual>& m)
+	{
+		return m._data + m._capacity;
+	}
+
 } // namespace hash_map
 
 template <typename TKey, typename TValue, typename Hash, typename KeyEqual>

+ 3 - 2
src/core/json/json.cpp

@@ -3,8 +3,9 @@
  * License: https://github.com/dbartolini/crown/blob/master/LICENSE
  */
 
-#include "core/containers/map.h"
+#include "core/containers/hash_map.h"
 #include "core/json/json.h"
+#include "core/json/json_object.h"
 #include "core/memory/temp_allocator.h"
 #include "core/strings/dynamic_string.h"
 #include "core/strings/string.h"
@@ -264,7 +265,7 @@ namespace json
 				json = next(json, ':');
 				json = skip_spaces(json);
 
-				map::set(object._map, fs_key, json);
+				hash_map::set(object._map, fs_key, json);
 
 				json = skip_value(json);
 				json = skip_spaces(json);

+ 23 - 9
src/core/json/json_object.h

@@ -5,11 +5,20 @@
 
 #pragma once
 
-#include "core/containers/map.h"
+#include "core/containers/hash_map.h"
 #include "core/json/types.h"
 
 namespace crown
 {
+template<>
+struct hash<FixedString>
+{
+	u32 operator()(const FixedString& val) const
+	{
+		return (u32)murmur32(val._data, val._length, 0);
+	}
+};
+
 /// Functions to manipulate JsonObject.
 ///
 /// @ingroup JSON
@@ -18,25 +27,30 @@ namespace json_object
 	/// Returns the number of keys in the object @a jo.
 	inline u32 size(const JsonObject& jo)
 	{
-		return map::size(jo._map);
+		return hash_map::size(jo._map);
 	}
 
 	/// Returns whether the object @a jo has the @a key.
 	inline bool has(const JsonObject& jo, const char* key)
 	{
-		return map::has(jo._map, FixedString(key));
+		return hash_map::has(jo._map, FixedString(key));
+	}
+
+	inline bool is_hole(const JsonObject& jo, const HashMap<FixedString, const char*>::Entry* entry)
+	{
+		return hash_map::is_hole(jo._map, entry);
 	}
 
 	/// Returns a pointer to the first item in the object @a jo.
-	inline const Map<FixedString, const char*>::Node* begin(const JsonObject& jo)
+	inline const HashMap<FixedString, const char*>::Entry* begin(const JsonObject& jo)
 	{
-		return map::begin(jo._map);
+		return hash_map::begin(jo._map);
 	}
 
 	/// Returns a pointer to the item following the last item in the object @a jo.
-	inline const Map<FixedString, const char*>::Node* end(const JsonObject& jo)
+	inline const HashMap<FixedString, const char*>::Entry* end(const JsonObject& jo)
 	{
-		return map::end(jo._map);
+		return hash_map::end(jo._map);
 	}
 
 } // namespace json_object
@@ -49,13 +63,13 @@ inline JsonObject::JsonObject(Allocator& a)
 /// Returns the value of the @a key or NULL.
 inline const char* JsonObject::operator[](const char* key) const
 {
-	return map::get(_map, FixedString(key), (const char*)NULL);
+	return hash_map::get(_map, FixedString(key), (const char*)NULL);
 }
 
 /// Returns the value of the @a key or NULL.
 inline const char* JsonObject::operator[](const FixedString& key) const
 {
-	return map::get(_map, key, (const char*)NULL);
+	return hash_map::get(_map, key, (const char*)NULL);
 }
 
 }

+ 4 - 3
src/core/json/sjson.cpp

@@ -3,7 +3,8 @@
  * License: https://github.com/dbartolini/crown/blob/master/LICENSE
  */
 
-#include "core/containers/map.h"
+#include "core/containers/hash_map.h"
+#include "core/json/json_object.h"
 #include "core/json/sjson.h"
 #include "core/memory/temp_allocator.h"
 #include "core/strings/dynamic_string.h"
@@ -326,7 +327,7 @@ namespace sjson
 			json = next(json, (*json == '=') ? '=' : ':');
 			json = skip_spaces(json);
 
-			map::set(object._map, fs_key, json);
+			hash_map::set(object._map, fs_key, json);
 
 			json = skip_value(json);
 			json = skip_spaces(json);
@@ -358,7 +359,7 @@ namespace sjson
 				json = next(json, (*json == '=') ? '=' : ':');
 				json = skip_spaces(json);
 
-				map::set(object._map, fs_key, json);
+				hash_map::set(object._map, fs_key, json);
 
 				json = skip_value(json);
 				json = skip_spaces(json);

+ 1 - 1
src/core/json/types.h

@@ -38,7 +38,7 @@ typedef Array<const char*> JsonArray;
 /// @ingroup JSON
 struct JsonObject
 {
-	Map<FixedString, const char*> _map;
+	HashMap<FixedString, const char*> _map;
 
 	JsonObject(Allocator& a);
 

+ 10 - 6
src/resource/material_resource.cpp

@@ -80,11 +80,13 @@ namespace material_resource_internal
 
 		auto cur = json_object::begin(object);
 		auto end = json_object::end(object);
-
 		for (; cur != end; ++cur)
 		{
-			const FixedString key = cur->pair.first;
-			const char* value     = cur->pair.second;
+			if (json_object::is_hole(object, cur))
+				continue;
+
+			const FixedString key = cur->first;
+			const char* value     = cur->second;
 
 			DynamicString texture(ta);
 			sjson::parse_string(value, texture);
@@ -117,11 +119,13 @@ namespace material_resource_internal
 
 		auto cur = json_object::begin(object);
 		auto end = json_object::end(object);
-
 		for (; cur != end; ++cur)
 		{
-			const FixedString key = cur->pair.first;
-			const char* value     = cur->pair.second;
+			if (json_object::is_hole(object, cur))
+				continue;
+
+			const FixedString key = cur->first;
+			const char* value     = cur->second;
 
 			UniformHandle uh;
 			uh.uniform_handle = 0;

+ 5 - 2
src/resource/mesh_resource.cpp

@@ -279,8 +279,11 @@ namespace mesh_resource_internal
 		auto end = json_object::end(geometries);
 		for (; cur != end; ++cur)
 		{
-			const FixedString key = cur->pair.first;
-			const char* geometry = cur->pair.second;
+			if (json_object::is_hole(geometries, cur))
+				continue;
+
+			const FixedString key = cur->first;
+			const char* geometry = cur->second;
 			const char* node = nodes[key];
 
 			const StringId32 name(key.data(), key.length());

+ 19 - 7
src/resource/physics_resource.cpp

@@ -309,8 +309,11 @@ namespace physics_config_resource_internal
 		auto end = json_object::end(object);
 		for (; cur != end; ++cur)
 		{
-			const FixedString key = cur->pair.first;
-			const char* value     = cur->pair.second;
+			if (json_object::is_hole(object, cur))
+				continue;
+
+			const FixedString key = cur->first;
+			const char* value     = cur->second;
 
 			JsonObject material(ta);
 			sjson::parse_object(value, material);
@@ -335,8 +338,11 @@ namespace physics_config_resource_internal
 		auto end = json_object::end(object);
 		for (; cur != end; ++cur)
 		{
-			const FixedString key = cur->pair.first;
-			const char* value     = cur->pair.second;
+			if (json_object::is_hole(object, cur))
+				continue;
+
+			const FixedString key = cur->first;
+			const char* value     = cur->second;
 
 			JsonObject actor(ta);
 			sjson::parse_object(value, actor);
@@ -416,7 +422,10 @@ namespace physics_config_resource_internal
 			auto end = json_object::end(object);
 			for (; cur != end; ++cur)
 			{
-				const FixedString key = cur->pair.first;
+				if (json_object::is_hole(object, cur))
+					continue;
+
+				const FixedString key = cur->first;
 				const StringId32 id   = StringId32(key.data(), key.length());
 
 				map::set(_filter_map, id, new_filter_mask());
@@ -426,8 +435,11 @@ namespace physics_config_resource_internal
 			end = json_object::end(object);
 			for (; cur != end; ++cur)
 			{
-				const FixedString key = cur->pair.first;
-				const char* value     = cur->pair.second;
+				if (json_object::is_hole(object, cur))
+					continue;
+
+				const FixedString key = cur->first;
+				const char* value     = cur->second;
 				const StringId32 id   = StringId32(key.data(), key.length());
 
 				TempAllocator4096 ta;

+ 25 - 10
src/resource/shader_resource.cpp

@@ -720,8 +720,11 @@ namespace shader_resource_internal
 			auto end = json_object::end(render_states);
 			for (; cur != end; ++cur)
 			{
+				if (json_object::is_hole(render_states, cur))
+					continue;
+
 				JsonObject obj(ta);
-				sjson::parse_object(cur->pair.second, obj);
+				sjson::parse_object(cur->second, obj);
 
 				const bool rgb_write_enable   = sjson::parse_bool(obj["rgb_write_enable"]);
 				const bool alpha_write_enable = sjson::parse_bool(obj["alpha_write_enable"]);
@@ -818,7 +821,7 @@ namespace shader_resource_internal
 				}
 
 				DynamicString key(ta);
-				key = cur->pair.first;
+				key = cur->first;
 
 				DATA_COMPILER_ASSERT(!map::has(_render_states, key)
 					, _opts
@@ -839,8 +842,11 @@ namespace shader_resource_internal
 			auto end = json_object::end(sampler_states);
 			for (; cur != end; ++cur)
 			{
+				if (json_object::is_hole(sampler_states, cur))
+					continue;
+
 				JsonObject obj(ta);
-				sjson::parse_object(cur->pair.second, obj);
+				sjson::parse_object(cur->second, obj);
 
 				const bool has_filter_min = json_object::has(obj, "filter_min");
 				const bool has_filter_mag = json_object::has(obj, "filter_mag");
@@ -913,7 +919,7 @@ namespace shader_resource_internal
 				}
 
 				DynamicString key(ta);
-				key = cur->pair.first;
+				key = cur->first;
 
 				DATA_COMPILER_ASSERT(!map::has(_sampler_states, key)
 					, _opts
@@ -934,8 +940,11 @@ namespace shader_resource_internal
 			auto end = json_object::end(bgfx_shaders);
 			for (; cur != end; ++cur)
 			{
+				if (json_object::is_hole(bgfx_shaders, cur))
+					continue;
+
 				JsonObject shader(ta);
-				sjson::parse_object(cur->pair.second, shader);
+				sjson::parse_object(cur->second, shader);
 
 				BgfxShader bgfxshader(default_allocator());
 				if (json_object::has(shader, "includes"))
@@ -956,7 +965,7 @@ namespace shader_resource_internal
 					parse_bgfx_samplers(shader["samplers"], bgfxshader);
 
 				DynamicString key(ta);
-				key = cur->pair.first;
+				key = cur->first;
 
 				DATA_COMPILER_ASSERT(!map::has(_bgfx_shaders, key)
 					, _opts
@@ -977,8 +986,11 @@ namespace shader_resource_internal
 			auto end = json_object::end(bgfx_samplers);
 			for (; cur != end; ++cur)
 			{
+				if (json_object::is_hole(bgfx_samplers, cur))
+					continue;
+
 				JsonObject sampler(ta);
-				sjson::parse_object(cur->pair.second, sampler);
+				sjson::parse_object(cur->second, sampler);
 
 				DynamicString sampler_state(ta);
 				sjson::parse_string(sampler["sampler_state"], sampler_state);
@@ -990,7 +1002,7 @@ namespace shader_resource_internal
 					);
 
 				DynamicString key(ta);
-				key = cur->pair.first;
+				key = cur->first;
 
 				DATA_COMPILER_ASSERT(!map::has(bgfxshader._samplers, key)
 					, _opts
@@ -1011,15 +1023,18 @@ namespace shader_resource_internal
 			auto end = json_object::end(shaders);
 			for (; cur != end; ++cur)
 			{
+				if (json_object::is_hole(shaders, cur))
+					continue;
+
 				JsonObject obj(ta);
-				sjson::parse_object(cur->pair.second, obj);
+				sjson::parse_object(cur->second, obj);
 
 				ShaderPermutation shader(default_allocator());
 				sjson::parse_string(obj["bgfx_shader"], shader._bgfx_shader);
 				sjson::parse_string(obj["render_state"], shader._render_state);
 
 				DynamicString key(ta);
-				key = cur->pair.first;
+				key = cur->first;
 
 				DATA_COMPILER_ASSERT(!map::has(_shaders, key)
 					, _opts

+ 5 - 2
src/resource/unit_compiler.cpp

@@ -359,9 +359,12 @@ void UnitCompiler::compile_unit_from_json(const char* json)
 			auto end = json_object::end(modified_components);
 			for (; cur != end; ++cur)
 			{
-				const FixedString key = cur->pair.first;
+				if (json_object::is_hole(modified_components, cur))
+					continue;
+
+				const FixedString key = cur->first;
 				const FixedString id(&key.data()[1], key.length()-1);
-				const char* value = cur->pair.second;
+				const char* value = cur->second;
 
 				u32 comp_index = component_index(prefab_root_components_original, id);
 				if (comp_index != UINT32_MAX)

+ 5 - 2
tools-imgui/widgets/dock.inl

@@ -1127,7 +1127,7 @@ namespace ImGui
 
 			auto cur = crown::json_object::begin(obj);
 			auto end = crown::json_object::end(obj);
-			for (uint32_t i = 0; i < end-cur; i++)
+			for (uint32_t i = 0; i < crown::json_object::size(obj); ++i)
 			{
 				Dock* dock = (Dock*) MemAlloc(sizeof(Dock));
 				m_docks.push_back(dock);
@@ -1135,7 +1135,10 @@ namespace ImGui
 
 			for (; cur != end; ++cur)
 			{
-				const char* value = cur->pair.second;
+				if (crown::json_object::is_hole(obj, cur))
+					continue;
+
+				const char* value = cur->second;
 				crown::JsonObject item(ta);
 				crown::sjson::parse_object(value, item);