Quellcode durchsuchen

Merge branch 'master' of github.com:taylor001/crown

Daniele Bartolini vor 10 Jahren
Ursprung
Commit
66b4d3e598

+ 6 - 6
src/console_server.cpp

@@ -122,8 +122,8 @@ ReadResult ConsoleServer::update_client(TCPSocket client)
 void ConsoleServer::process(TCPSocket client, const char* json)
 {
 	TempAllocator4096 ta;
-	Map<DynamicString, const char*> root(ta);
-	json::parse_object(json, root);
+	JsonObject root(ta);
+	json::parse(json, root);
 
 	DynamicString type(ta);
 	json::parse_string(root["type"], type);
@@ -142,8 +142,8 @@ void ConsoleServer::process_ping(TCPSocket client, const char* /*json*/)
 void ConsoleServer::process_script(TCPSocket /*client*/, const char* json)
 {
 	TempAllocator4096 ta;
-	Map<DynamicString, const char*> root(ta);
-	json::parse_object(json, root);
+	JsonObject root(ta);
+	json::parse(json, root);
 
 	DynamicString script(ta);
 	json::parse_string(root["script"], script);
@@ -153,8 +153,8 @@ void ConsoleServer::process_script(TCPSocket /*client*/, const char* json)
 void ConsoleServer::process_command(TCPSocket /*client*/, const char* json)
 {
 	TempAllocator4096 ta;
-	Map<DynamicString, const char*> root(ta);
-	json::parse_object(json, root);
+	JsonObject root(ta);
+	json::parse(json, root);
 
 	DynamicString cmd(ta);
 	json::parse_string(root["command"], cmd);

+ 26 - 9
src/core/json/json.cpp

@@ -59,17 +59,17 @@ namespace json
 		return json;
 	}
 
-	JSONValueType::Enum type(const char* json)
+	JsonValueType::Enum type(const char* json)
 	{
 		CE_ASSERT_NOT_NULL(json);
 
 		switch (*json)
 		{
-			case '"': return JSONValueType::STRING;
-			case '{': return JSONValueType::OBJECT;
-			case '[': return JSONValueType::ARRAY;
-			case '-': return JSONValueType::NUMBER;
-			default: return (isdigit(*json)) ? JSONValueType::NUMBER : (*json == 'n' ? JSONValueType::NIL : JSONValueType::BOOL);
+			case '"': return JsonValueType::STRING;
+			case '{': return JsonValueType::OBJECT;
+			case '[': return JsonValueType::ARRAY;
+			case '-': return JsonValueType::NUMBER;
+			default: return (isdigit(*json)) ? JsonValueType::NUMBER : (*json == 'n' ? JsonValueType::NIL : JsonValueType::BOOL);
 		}
 	}
 
@@ -208,7 +208,7 @@ namespace json
 		return (float) parse_number(json);
 	}
 
-	void parse_array(const char* json, Array<const char*>& array)
+	void parse_array(const char* json, JsonArray& array)
 	{
 		CE_ASSERT_NOT_NULL(json);
 
@@ -244,7 +244,7 @@ namespace json
 		CE_FATAL("Bad array");
 	}
 
-	void parse_object(const char* json, Map<DynamicString, const char*>& object)
+	void parse_object(const char* json, JsonObject& object)
 	{
 		CE_ASSERT_NOT_NULL(json);
 
@@ -262,16 +262,20 @@ namespace json
 
 			while (*json)
 			{
+				const char* key_begin = *json == '"' ? (json + 1) : json;
+
 				TempAllocator256 ta;
 				DynamicString key(ta);
 				parse_string(json, key);
 
+				FixedString fs_key(key_begin, key.length());
+
 				json = skip_string(json);
 				json = skip_spaces(json);
 				json = next(json, ':');
 				json = skip_spaces(json);
 
-				map::set(object, key, json);
+				map::set(object, fs_key, json);
 
 				json = skip_value(json);
 				json = skip_spaces(json);
@@ -289,5 +293,18 @@ namespace json
 
 		CE_FATAL("Bad object");
 	}
+
+	void parse(const char* json, JsonObject& object)
+	{
+		CE_ASSERT_NOT_NULL(json);
+		parse_object(json, object);
+	}
+
+	void parse(Buffer& json, JsonObject& object)
+	{
+		array::push_back(json, '\0');
+		array::pop_back(json);
+		parse(array::begin(json), object);
+	}
 } // namespace json
 } // namespace crown

+ 10 - 22
src/core/json/json.h

@@ -5,37 +5,19 @@
 
 #pragma once
 
+#include "json_types.h"
 #include "dynamic_string.h"
-#include "container_types.h"
 
 namespace crown
 {
 
-/// @defgroup JSON
-
-/// Enumerates JSON value types.
-///
-/// @ingroup JSON
-struct JSONValueType
-{
-	enum Enum
-	{
-		NIL,
-		BOOL,
-		NUMBER,
-		STRING,
-		ARRAY,
-		OBJECT
-	};
-};
-
 /// Functions to parse JSON-encoded strings.
 ///
 /// @ingroup JSON
 namespace json
 {
 	/// Returns the data type of the JSON string @a json.
-	JSONValueType::Enum type(const char* json);
+	JsonValueType::Enum type(const char* json);
 
 	/// Parses the JSON string @a json ad puts it into @a string.
 	void parse_string(const char* json, DynamicString& string);
@@ -54,10 +36,16 @@ namespace json
 
 	/// Parses the JSON array @a json and puts it into @a array as pointers to
 	/// the corresponding items into the original @a json string.
-	void parse_array(const char* json, Array<const char*>& array);
+	void parse_array(const char* json, JsonArray& array);
 
 	/// Parses the JSON object @a json and puts it into @a object as map from
 	/// key to pointer to the corresponding value into the original string @a json.
-	void parse_object(const char* json, Map<DynamicString, const char*>& object);
+	void parse_object(const char* json, JsonObject& object);
+
+	/// Parses the NJSON-encoded @a json.
+	void parse(const char* json, JsonObject& object);
+
+	/// Parses the NJSON-encoded @a json.
+	void parse(Buffer& json, JsonObject& object);
 } // namespace json
 } // namespace crown

+ 12 - 12
src/core/json/json_parser.cpp

@@ -332,7 +332,7 @@ bool JSONElement::is_nil() const
 {
 	if (_at != NULL)
 	{
-		return njson::type(_at) == NJSONValueType::NIL;
+		return njson::type(_at) == JsonValueType::NIL;
 	}
 
 	return true;
@@ -342,7 +342,7 @@ bool JSONElement::is_bool() const
 {
 	if (_at != NULL)
 	{
-		return njson::type(_at) == NJSONValueType::BOOL;
+		return njson::type(_at) == JsonValueType::BOOL;
 	}
 
 	return false;
@@ -352,7 +352,7 @@ bool JSONElement::is_number() const
 {
 	if (_at != NULL)
 	{
-		return njson::type(_at) == NJSONValueType::NUMBER;
+		return njson::type(_at) == JsonValueType::NUMBER;
 	}
 
 	return false;
@@ -362,7 +362,7 @@ bool JSONElement::is_string() const
 {
 	if (_at != NULL)
 	{
-		return njson::type(_at) == NJSONValueType::STRING;
+		return njson::type(_at) == JsonValueType::STRING;
 	}
 
 	return false;
@@ -372,7 +372,7 @@ bool JSONElement::is_array() const
 {
 	if (_at != NULL)
 	{
-		return njson::type(_at) == NJSONValueType::ARRAY;
+		return njson::type(_at) == JsonValueType::ARRAY;
 	}
 
 	return false;
@@ -382,7 +382,7 @@ bool JSONElement::is_object() const
 {
 	if (_at != NULL)
 	{
-		return njson::type(_at) == NJSONValueType::OBJECT;
+		return njson::type(_at) == JsonValueType::OBJECT;
 	}
 
 	return false;
@@ -397,34 +397,34 @@ uint32_t JSONElement::size() const
 
 	switch(njson::type(_at))
 	{
-		case NJSONValueType::NIL:
+		case JsonValueType::NIL:
 		{
 			return 1;
 		}
-		case NJSONValueType::OBJECT:
+		case JsonValueType::OBJECT:
 		{
 			Map<DynamicString, const char*> object(default_allocator());
 			njson::parse(_at, object);
 			return map::size(object);
 		}
-		case NJSONValueType::ARRAY:
+		case JsonValueType::ARRAY:
 		{
 			Array<const char*> array(default_allocator());
 			njson::parse_array(_at, array);
 			return array::size(array);
 		}
-		case NJSONValueType::STRING:
+		case JsonValueType::STRING:
 		{
 			TempAllocator256 ta;
 			DynamicString string(ta);
 			njson::parse_string(_at, string);
 			return string.length();
 		}
-		case NJSONValueType::NUMBER:
+		case JsonValueType::NUMBER:
 		{
 			return 1;
 		}
-		case NJSONValueType::BOOL:
+		case JsonValueType::BOOL:
 		{
 			return 1;
 		}

+ 35 - 0
src/core/json/json_types.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012-2015 Daniele Bartolini and individual contributors.
+ * License: https://github.com/taylor001/crown/blob/master/LICENSE
+ */
+
+#pragma once
+
+#include "container_types.h"
+#include "fixed_string.h"
+
+namespace crown
+{
+
+/// @defgroup JSON
+
+/// Enumerates JSON value types.
+///
+/// @ingroup JSON
+struct JsonValueType
+{
+	enum Enum
+	{
+		NIL,
+		BOOL,
+		NUMBER,
+		STRING,
+		ARRAY,
+		OBJECT
+	};
+};
+
+typedef Array<const char*> JsonArray;
+typedef Map<FixedString, const char*> JsonObject;
+
+} // namespace crown

+ 203 - 6
src/core/json/njson.cpp

@@ -7,6 +7,7 @@
 #include "string_utils.h"
 #include "temp_allocator.h"
 #include "map.h"
+#include "quaternion.h"
 
 namespace crown
 {
@@ -101,17 +102,17 @@ namespace njson
 		return json;
 	}
 
-	NJSONValueType::Enum type(const char* json)
+	JsonValueType::Enum type(const char* json)
 	{
 		CE_ASSERT_NOT_NULL(json);
 
 		switch (*json)
 		{
-			case '"': return NJSONValueType::STRING;
-			case '{': return NJSONValueType::OBJECT;
-			case '[': return NJSONValueType::ARRAY;
-			case '-': return NJSONValueType::NUMBER;
-			default: return (isdigit(*json)) ? NJSONValueType::NUMBER : (*json == 'n' ? NJSONValueType::NIL : NJSONValueType::BOOL);
+			case '"': return JsonValueType::STRING;
+			case '{': return JsonValueType::OBJECT;
+			case '[': return JsonValueType::ARRAY;
+			case '-': return JsonValueType::NUMBER;
+			default: return (isdigit(*json)) ? JsonValueType::NUMBER : (*json == 'n' ? JsonValueType::NIL : JsonValueType::BOOL);
 		}
 	}
 
@@ -385,5 +386,201 @@ namespace njson
 		else
 			parse_root_object(json, object);
 	}
+
+	void parse_root_object(const char* json, JsonObject& object)
+	{
+		CE_ASSERT_NOT_NULL(json);
+
+		while (*json)
+		{
+			const char* key_begin = *json == '"' ? (json + 1) : json;
+
+			TempAllocator256 ta;
+			DynamicString key(ta);
+			json = parse_key(json, key);
+
+			FixedString fs_key(key_begin, key.length());
+
+			json = skip_spaces(json);
+			json = next(json, '=');
+			json = skip_spaces(json);
+
+			map::set(object, fs_key, json);
+
+			json = skip_value(json);
+			json = skip_spaces(json);
+		}
+	}
+
+	void parse_object(const char* json, JsonObject& object)
+	{
+		CE_ASSERT_NOT_NULL(json);
+
+		if (*json == '{')
+		{
+			json = next(json, '{');
+
+			json = skip_spaces(json);
+
+			if (*json == '}')
+			{
+				next(json, '}');
+				return;
+			}
+
+			while (*json)
+			{
+				const char* key_begin = *json == '"' ? (json + 1) : json;
+
+				TempAllocator256 ta;
+				DynamicString key(ta);
+				json = parse_key(json, key);
+
+				FixedString fs_key(key_begin, key.length());
+
+				json = skip_spaces(json);
+				json = next(json, '=');
+				json = skip_spaces(json);
+
+				map::set(object, fs_key, json);
+
+				json = skip_value(json);
+				json = skip_spaces(json);
+
+				if (*json == '}')
+				{
+					next(json, '}');
+					return;
+				}
+
+				json = skip_spaces(json);
+			}
+		}
+
+		CE_FATAL("Bad object");
+	}
+
+	void parse(const char* json, JsonObject& object)
+	{
+		CE_ASSERT_NOT_NULL(json);
+
+		json = skip_spaces(json);
+
+		if (*json == '{')
+			parse_object(json, object);
+		else
+			parse_root_object(json, object);
+	}
+
+	void parse(Buffer& json, JsonObject& object)
+	{
+		array::push_back(json, '\0');
+		array::pop_back(json);
+		parse(array::begin(json), object);
+	}
 } // namespace njson
+
+namespace njson
+{
+	Vector2 parse_vector2(const char* json)
+	{
+		TempAllocator64 ta;
+		JsonArray array(ta);
+		njson::parse_array(json, array);
+
+		Vector2 v;
+		v.x = njson::parse_float(array[0]);
+		v.y = njson::parse_float(array[1]);
+		return v;
+	}
+
+	Vector3 parse_vector3(const char* json)
+	{
+		TempAllocator64 ta;
+		JsonArray array(ta);
+		njson::parse_array(json, array);
+
+		Vector3 v;
+		v.x = njson::parse_float(array[0]);
+		v.y = njson::parse_float(array[1]);
+		v.z = njson::parse_float(array[2]);
+		return v;
+	}
+
+	Vector4 parse_vector4(const char* json)
+	{
+		TempAllocator64 ta;
+		JsonArray array(ta);
+		njson::parse_array(json, array);
+
+		Vector4 v;
+		v.x = njson::parse_float(array[0]);
+		v.y = njson::parse_float(array[1]);
+		v.z = njson::parse_float(array[2]);
+		v.w = njson::parse_float(array[3]);
+		return v;
+	}
+
+	Quaternion parse_quaternion(const char* json)
+	{
+		TempAllocator64 ta;
+		JsonArray array(ta);
+		njson::parse_array(json, array);
+
+		Vector3 axis;
+		axis.x = njson::parse_float(array[0]);
+		axis.y = njson::parse_float(array[1]);
+		axis.z = njson::parse_float(array[2]);
+
+		float angle = njson::parse_float(array[3]);
+
+		return quaternion(axis, angle);
+	}
+
+	Matrix4x4 parse_matrix4x4(const char* json)
+	{
+		TempAllocator128 ta;
+		JsonArray array(ta);
+		njson::parse_array(json, array);
+
+		Matrix4x4 m;
+		m.x.x = njson::parse_float(array[ 0]);
+		m.x.y = njson::parse_float(array[ 1]);
+		m.x.z = njson::parse_float(array[ 2]);
+		m.x.w = njson::parse_float(array[ 3]);
+
+		m.y.x = njson::parse_float(array[ 4]);
+		m.y.y = njson::parse_float(array[ 5]);
+		m.y.z = njson::parse_float(array[ 6]);
+		m.y.w = njson::parse_float(array[ 7]);
+
+		m.z.x = njson::parse_float(array[ 8]);
+		m.z.y = njson::parse_float(array[ 9]);
+		m.z.z = njson::parse_float(array[10]);
+		m.z.w = njson::parse_float(array[11]);
+
+		m.t.x = njson::parse_float(array[12]);
+		m.t.y = njson::parse_float(array[13]);
+		m.t.z = njson::parse_float(array[14]);
+		m.t.w = njson::parse_float(array[15]);
+		return m;
+	}
+
+	StringId32 parse_string_id(const char* json)
+	{
+		TempAllocator1024 ta;
+		DynamicString str(ta);
+		njson::parse_string(json, str);
+		return str.to_string_id();
+	}
+
+	ResourceId parse_resource_id(const char* json)
+	{
+		TempAllocator1024 ta;
+		DynamicString str(ta);
+		njson::parse_string(json, str);
+		return ResourceId(str.c_str());
+	}
+} // namespace json
+
 } // namespace crown

+ 44 - 21
src/core/json/njson.h

@@ -5,37 +5,20 @@
 
 #pragma once
 
+#include "json_types.h"
+#include "math_types.h"
 #include "dynamic_string.h"
-#include "container_types.h"
 
 namespace crown
 {
 
-/// @defgroup JSON
-
-/// Enumerates JSON value types.
-///
-/// @ingroup JSON
-struct NJSONValueType
-{
-	enum Enum
-	{
-		NIL,
-		BOOL,
-		NUMBER,
-		STRING,
-		ARRAY,
-		OBJECT
-	};
-};
-
 /// Functions to parse NJSON-encoded strings.
 ///
 /// @ingroup JSON
 namespace njson
 {
 	/// Returns the data type of the NJSON string @a json.
-	NJSONValueType::Enum type(const char* json);
+	JsonValueType::Enum type(const char* json);
 
 	/// Parses the NJSON string @a json ad puts it into @a string.
 	void parse_string(const char* json, DynamicString& string);
@@ -54,7 +37,7 @@ namespace njson
 
 	/// Parses the NJSON array @a json and puts it into @a array as pointers to
 	/// the corresponding items into the original @a json string.
-	void parse_array(const char* json, Array<const char*>& array);
+	void parse_array(const char* json, JsonArray& array);
 
 	/// Parses the NJSON object @a json and puts it into @a object as map from
 	/// key to pointer to the corresponding value into the original string @a json.
@@ -62,5 +45,45 @@ namespace njson
 
 	/// Parses the NJSON-encoded @a json.
 	void parse(const char* json, Map<DynamicString, const char*>& object);
+
+	/// Parses the NJSON object @a json and puts it into @a object as map from
+	/// key to pointer to the corresponding value into the original string @a json.
+	void parse_object(const char* json, JsonObject& object);
+
+	/// Parses the NJSON-encoded @a json.
+	void parse(const char* json, JsonObject& object);
+
+	/// Parses the NJSON-encoded @a json.
+	void parse(Buffer& json, JsonObject& object);
 } // namespace njson
+
+namespace njson
+{
+	/// Returns the array @a json as Vector2.
+	/// @note Vector2 = [x, y]
+	Vector2 parse_vector2(const char* json);
+
+	/// Returns the array @a json as Vector3.
+	/// @note Vector3 = [x, y, z]
+	Vector3 parse_vector3(const char* json);
+
+	/// Returns the array @a json as Vector4.
+	/// @note Vector4 = [x, y, z, w]
+	Vector4 parse_vector4(const char* json);
+
+	/// Returns the array @a json as Quaternion.
+	/// @note Quaternion = [x, y, z, w]
+	Quaternion parse_quaternion(const char* json);
+
+	/// Returns the array @a json as Matrix4x4.
+	/// @note Matrix4x4 = [x, x, x, x, y, y, y, y, z, z, z, z, t, t, t, t]
+	Matrix4x4 parse_matrix4x4(const char* json);
+
+	/// Returns the string @a json as StringId32.
+	StringId32 parse_string_id(const char* json);
+
+	/// Returns the string @a json as ResourceId.
+	ResourceId parse_resource_id(const char* json);
+}
+
 } // namespace crown

+ 72 - 0
src/core/strings/fixed_string.h

@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012-2015 Daniele Bartolini and individual contributors.
+ * License: https://github.com/taylor001/crown/blob/master/LICENSE
+ */
+
+#pragma once
+
+#include "string_utils.h"
+#include <algorithm>
+
+namespace crown
+{
+
+class FixedString
+{
+public:
+
+	FixedString()
+		: _length(0)
+		, _data(NULL)
+	{
+	}
+
+	FixedString(const char* str)
+		: _length(strlen(str))
+		, _data(str)
+	{
+	}
+
+	FixedString(const char* str, uint32_t len)
+		: _length(len)
+		, _data(str)
+	{
+	}
+
+	FixedString(const FixedString& b)
+		: _length(b._length)
+		, _data(b._data)
+	{
+	}
+
+	FixedString& operator=(const char* str)
+	{
+		_length = strlen(str);
+		_data = str;
+		return *this;
+	}
+
+	bool operator==(const char* str) const
+	{
+		const uint32_t len = strlen(str);
+		return _length == len && !strncmp(_data, str, len);
+	}
+
+	bool operator==(const FixedString& b) const
+	{
+		return (_length == b._length) && !strncmp(_data, b._data, _length);
+	}
+
+	bool operator<(const FixedString& b) const
+	{
+		const uint32_t len = std::max(_length, b._length);
+		return strncmp(_data, b._data, len) < 0;
+	}
+
+private:
+
+	uint32_t _length;
+	const char* _data;
+};
+
+} // namespace crown

+ 9 - 7
src/device.cpp

@@ -18,7 +18,6 @@
 #include "resource_package.h"
 #include "types.h"
 #include "world.h"
-#include "json_parser.h"
 #include "filesystem.h"
 #include "path.h"
 #include "disk_filesystem.h"
@@ -27,6 +26,8 @@
 #include "profiler.h"
 #include "console_server.h"
 #include "input_device.h"
+#include "njson.h"
+#include "map.h"
 
 #if CROWN_PLATFORM_ANDROID
 	#include "apk_filesystem.h"
@@ -413,7 +414,7 @@ bool Device::process_events()
 
 void Device::read_config()
 {
-	TempAllocator1024 ta;
+	TempAllocator4096 ta;
 	DynamicString project_path(ta);
 
 	if (_device_options.project() != NULL)
@@ -428,12 +429,13 @@ void Device::read_config()
 
 	_resource_manager->load(CONFIG_TYPE, config_name);
 	_resource_manager->flush();
-	const char* config_file = (const char*)_resource_manager->get(CONFIG_TYPE, config_name);
+	const char* cfile = (const char*)_resource_manager->get(CONFIG_TYPE, config_name);
 
-	JSONParser config(config_file);
-	JSONElement root = config.root();
-	_boot_script_id = root.key("boot_script").to_resource_id();
-	_boot_package_id = root.key("boot_package").to_resource_id();
+	JsonObject config(ta);
+	njson::parse(cfile, config);
+
+	_boot_script_id  = njson::parse_resource_id(config["boot_script"]);
+	_boot_package_id = njson::parse_resource_id(config["boot_package"]);
 
 	_resource_manager->unload(CONFIG_TYPE, config_name);
 }

+ 34 - 24
src/resource/font_resource.cpp

@@ -4,61 +4,71 @@
  */
 
 #include "font_resource.h"
-#include "json_parser.h"
 #include "allocator.h"
 #include "filesystem.h"
 #include "string_utils.h"
 #include "compile_options.h"
+#include "njson.h"
+#include "map.h"
 
 namespace crown
 {
 namespace font_resource
 {
-	void parse_glyph(JSONElement e, FontGlyphData& glyph)
+	void parse_glyph(const char* json, FontGlyphData& glyph)
 	{
-		glyph.id        = e.key("id").to_int();
-		glyph.x         = e.key("x").to_int();
-		glyph.y         = e.key("y").to_int();
-		glyph.width     = e.key("width").to_int();
-		glyph.height    = e.key("height").to_int();
-		glyph.x_offset  = e.key("x_offset").to_float();
-		glyph.y_offset  = e.key("y_offset").to_float();
-		glyph.x_advance = e.key("x_advance").to_float();
+		TempAllocator512 ta;
+		JsonObject obj(ta);
+		njson::parse(json, obj);
+
+		glyph.id        = njson::parse_int(obj["id"]);
+		glyph.x         = njson::parse_int(obj["x"]);
+		glyph.y         = njson::parse_int(obj["y"]);
+		glyph.width     = njson::parse_int(obj["width"]);
+		glyph.height    = njson::parse_int(obj["height"]);
+		glyph.x_offset  = njson::parse_float(obj["x_offset"]);
+		glyph.y_offset  = njson::parse_float(obj["y_offset"]);
+		glyph.x_advance = njson::parse_float(obj["x_advance"]);
 	}
 
 	void compile(const char* path, CompileOptions& opts)
 	{
 		Buffer buf = opts.read(path);
-		JSONParser json(buf);
-		JSONElement root = json.root();
 
-		Array<FontGlyphData> m_glyphs(default_allocator());
-		JSONElement count = root.key("count");
-		JSONElement size = root.key("size");
-		JSONElement font_size = root.key("font_size");
-		JSONElement glyphs = root.key("glyphs");
+		TempAllocator4096 ta;
+		JsonObject object(ta);
+		JsonArray glyphs(ta);
+
+		njson::parse(buf, object);
+		njson::parse_array(object["glyphs"], glyphs);
 
-		uint32_t num_glyphs = count.to_int();
+		const uint32_t count      = njson::parse_int(object["count"]);
+		const uint32_t size       = njson::parse_int(object["size"]);
+		const uint32_t font_size  = njson::parse_int(object["font_size"]);
+		const uint32_t num_glyphs = array::size(glyphs);
+
+		Array<FontGlyphData> m_glyphs(default_allocator());
 
-		for (uint32_t i = 0; i < num_glyphs; i++)
+		for (uint32_t i = 0; i < num_glyphs; ++i)
 		{
 			FontGlyphData data;
 			parse_glyph(glyphs[i], data);
 			array::push_back(m_glyphs, data);
 		}
 
+		// Write
 		FontResource fr;
-		fr.version = FONT_VERSION;
-		fr.num_glyphs = array::size(m_glyphs);
-		fr.texture_size = size.to_int();
-		fr.font_size = font_size.to_int();
+		fr.version      = FONT_VERSION;
+		fr.num_glyphs   = array::size(m_glyphs);
+		fr.texture_size = size;
+		fr.font_size    = font_size;
 
 		opts.write(fr.version);
 		opts.write(fr.num_glyphs);
 		opts.write(fr.texture_size);
 		opts.write(fr.font_size);
 
-		for (uint32_t i = 0; i < array::size(m_glyphs); i++)
+		for (uint32_t i = 0; i < array::size(m_glyphs); ++i)
 		{
 			opts.write(m_glyphs[i].id);
 			opts.write(m_glyphs[i].x);

+ 58 - 48
src/resource/package_resource.cpp

@@ -5,12 +5,13 @@
 
 #include "file.h"
 #include "filesystem.h"
-#include "json_parser.h"
 #include "package_resource.h"
 #include "temp_allocator.h"
 #include "reader_writer.h"
 #include "compile_options.h"
 #include "array.h"
+#include "njson.h"
+#include "map.h"
 
 namespace crown
 {
@@ -19,112 +20,121 @@ namespace package_resource
 	void compile(const char* path, CompileOptions& opts)
 	{
 		Buffer buf = opts.read(path);
-		JSONParser json(buf);
-		JSONElement root = json.root();
-
-		JSONElement texture  = root.key_or_nil("texture");
-		JSONElement script   = root.key_or_nil("lua");
-		JSONElement sound    = root.key_or_nil("sound");
-		JSONElement mesh     = root.key_or_nil("mesh");
-		JSONElement unit     = root.key_or_nil("unit");
-		JSONElement sprite   = root.key_or_nil("sprite");
-		JSONElement material = root.key_or_nil("material");
-		JSONElement font     = root.key_or_nil("font");
-		JSONElement level    = root.key_or_nil("level");
-		JSONElement phyconf  = root.key_or_nil("physics_config");
-		JSONElement shader   = root.key_or_nil("shader");
-		JSONElement sprite_animation = root.key_or_nil("sprite_animation");
-
-		const uint32_t num_textures  = texture.is_nil() ? 0 : texture.size();
-		const uint32_t num_scripts   = script.is_nil() ? 0 : script.size();
-		const uint32_t num_sounds    = sound.is_nil() ? 0 : sound.size();
-		const uint32_t num_meshes    = mesh.is_nil() ? 0 : mesh.size();
-		const uint32_t num_units     = unit.is_nil() ? 0 : unit.size();
-		const uint32_t num_sprites   = sprite.is_nil() ? 0 : sprite.size();
-		const uint32_t num_materials = material.is_nil() ? 0 : material.size();
-		const uint32_t num_fonts     = font.is_nil() ? 0 : font.size();
-		const uint32_t num_levels    = level.is_nil() ? 0 : level.size();
-		const uint32_t num_phyconfs  = phyconf.is_nil() ? 0 : phyconf.size();
-		const uint32_t num_shaders   = shader.is_nil() ? 0 : shader.size();
-		const uint32_t num_sprite_animations = sprite_animation.is_nil() ? 0 : sprite_animation.size();
+
+		TempAllocator4096 ta;
+		JsonObject object(ta);
+		njson::parse(buf, object);
+
+		JsonArray texture(ta);
+		JsonArray script(ta);
+		JsonArray sound(ta);
+		JsonArray mesh(ta);
+		JsonArray unit(ta);
+		JsonArray sprite(ta);
+		JsonArray material(ta);
+		JsonArray font(ta);
+		JsonArray level(ta);
+		JsonArray phyconf(ta);
+		JsonArray shader(ta);
+		JsonArray sprite_animation(ta);
+
+		if (map::has(object, FixedString("texture")))          njson::parse_array(object["texture"], texture);
+		if (map::has(object, FixedString("lua")))              njson::parse_array(object["lua"], script);
+		if (map::has(object, FixedString("sound")))            njson::parse_array(object["sound"], sound);
+		if (map::has(object, FixedString("mesh")))             njson::parse_array(object["mesh"], mesh);
+		if (map::has(object, FixedString("unit")))             njson::parse_array(object["unit"], unit);
+		if (map::has(object, FixedString("sprite")))           njson::parse_array(object["sprite"], sprite);
+		if (map::has(object, FixedString("material")))         njson::parse_array(object["material"], material);
+		if (map::has(object, FixedString("font")))             njson::parse_array(object["font"], font);
+		if (map::has(object, FixedString("level")))            njson::parse_array(object["level"], level);
+		if (map::has(object, FixedString("physics_config")))   njson::parse_array(object["physics_config"], phyconf);
+		if (map::has(object, FixedString("shader")))           njson::parse_array(object["shader"], shader);
+		if (map::has(object, FixedString("sprite_animation"))) njson::parse_array(object["sprite_animation"], sprite_animation);
+
+		const uint32_t num_textures    = array::size(texture);
+		const uint32_t num_scripts     = array::size(script);
+		const uint32_t num_sounds      = array::size(sound);
+		const uint32_t num_meshes      = array::size(mesh);
+		const uint32_t num_units       = array::size(unit);
+		const uint32_t num_sprites     = array::size(sprite);
+		const uint32_t num_materials   = array::size(material);
+		const uint32_t num_fonts       = array::size(font);
+		const uint32_t num_levels      = array::size(level);
+		const uint32_t num_phyconfs    = array::size(phyconf);
+		const uint32_t num_shaders     = array::size(shader);
+		const uint32_t num_sanimations = array::size(sprite_animation);
 
 		Array<PackageResource::Resource> resources(default_allocator());
 
 		for (uint32_t i = 0; i < num_textures; ++i)
 		{
-			PackageResource::Resource res(TEXTURE_TYPE, texture[i].to_resource_id());
+			PackageResource::Resource res(TEXTURE_TYPE, njson::parse_resource_id(texture[i]));
 			array::push_back(resources, res);
 		}
 
 		for (uint32_t i = 0; i < num_scripts; ++i)
 		{
-			PackageResource::Resource res(SCRIPT_TYPE, script[i].to_resource_id());
+			PackageResource::Resource res(SCRIPT_TYPE, njson::parse_resource_id(script[i]));
 			array::push_back(resources, res);
 		}
 
 		for (uint32_t i = 0; i < num_sounds; ++i)
 		{
-			PackageResource::Resource res(SOUND_TYPE, sound[i].to_resource_id());
+			PackageResource::Resource res(SOUND_TYPE, njson::parse_resource_id(sound[i]));
 			array::push_back(resources, res);
 		}
 
 		for (uint32_t i = 0; i < num_meshes; ++i)
 		{
-			PackageResource::Resource res(MESH_TYPE, mesh[i].to_resource_id());
+			PackageResource::Resource res(MESH_TYPE, njson::parse_resource_id(mesh[i]));
 			array::push_back(resources, res);
 		}
 
 		for (uint32_t i = 0; i < num_units; ++i)
 		{
-			PackageResource::Resource res(UNIT_TYPE, unit[i].to_resource_id());
+			PackageResource::Resource res(UNIT_TYPE, njson::parse_resource_id(unit[i]));
 			array::push_back(resources, res);
 		}
 
 		for (uint32_t i = 0; i < num_sprites; ++i)
 		{
-			PackageResource::Resource res(SPRITE_TYPE, sprite[i].to_resource_id());
-			array::push_back(resources, res);
-		}
-
-		for (uint32_t i = 0; i < num_physics; ++i)
-		{
-			PackageResource::Resource res(PHYSICS_TYPE, physics[i].to_resource_id());
+			PackageResource::Resource res(SPRITE_TYPE, njson::parse_resource_id(sprite[i]));
 			array::push_back(resources, res);
 		}
 
 		for (uint32_t i = 0; i < num_materials; ++i)
 		{
-			PackageResource::Resource res(MATERIAL_TYPE, material[i].to_resource_id());
+			PackageResource::Resource res(MATERIAL_TYPE, njson::parse_resource_id(material[i]));
 			array::push_back(resources, res);
 		}
 
 		for (uint32_t i = 0; i < num_fonts; ++i)
 		{
-			PackageResource::Resource res(FONT_TYPE, font[i].to_resource_id());
+			PackageResource::Resource res(FONT_TYPE, njson::parse_resource_id(font[i]));
 			array::push_back(resources, res);
 		}
 
 		for (uint32_t i = 0; i < num_levels; ++i)
 		{
-			PackageResource::Resource res(LEVEL_TYPE, level[i].to_resource_id());
+			PackageResource::Resource res(LEVEL_TYPE, njson::parse_resource_id(level[i]));
 			array::push_back(resources, res);
 		}
 
 		for (uint32_t i = 0; i < num_phyconfs; ++i)
 		{
-			PackageResource::Resource res(PHYSICS_CONFIG_TYPE, phyconf[i].to_resource_id());
+			PackageResource::Resource res(PHYSICS_CONFIG_TYPE, njson::parse_resource_id(phyconf[i]));
 			array::push_back(resources, res);
 		}
 
 		for (uint32_t i = 0; i < num_shaders; ++i)
 		{
-			PackageResource::Resource res(SHADER_TYPE, shader[i].to_resource_id());
+			PackageResource::Resource res(SHADER_TYPE, njson::parse_resource_id(shader[i]));
 			array::push_back(resources, res);
 		}
 
-		for (uint32_t i = 0; i < num_sprite_animations; ++i)
+		for (uint32_t i = 0; i < num_sanimations; ++i)
 		{
-			PackageResource::Resource res(SPRITE_ANIMATION_TYPE, sprite_animation[i].to_resource_id());
+			PackageResource::Resource res(SPRITE_ANIMATION_TYPE, njson::parse_resource_id(sprite_animation[i]));
 			array::push_back(resources, res);
 		}
 

+ 21 - 17
src/resource/sound_resource.cpp

@@ -6,8 +6,9 @@
 #include "sound_resource.h"
 #include "dynamic_string.h"
 #include "filesystem.h"
-#include "json_parser.h"
 #include "compile_options.h"
+#include "njson.h"
+#include "map.h"
 
 namespace crown
 {
@@ -15,28 +16,31 @@ namespace sound_resource
 {
 	struct WAVHeader
 	{
-		char    riff[4];			// Should contain 'RIFF'
-		int32_t chunk_size;			// Not Needed
-		char    wave[4];			// Should contain 'WAVE'
-		char    fmt[4];				// Should contain 'fmt '
-		int32_t fmt_size;			// Size of format chunk
-		int16_t fmt_tag;			// Identifies way data is stored, 1 means no compression
-		int16_t fmt_channels;		// Channel, 1 means mono, 2 means stereo
-		int32_t fmt_sample_rate;	// Samples per second
-		int32_t fmt_avarage;		// Avarage bytes per sample
-		int16_t fmt_block_align;	// Block alignment
-		int16_t fmt_bits_ps;		// Number of bits per sample
-		char    data[4];			// Should contain 'data'
-		int32_t data_size;			// Data dimension
+		char    riff[4];         // Should contain 'RIFF'
+		int32_t chunk_size;      // Not Needed
+		char    wave[4];         // Should contain 'WAVE'
+		char    fmt[4];          // Should contain 'fmt '
+		int32_t fmt_size;        // Size of format chunk
+		int16_t fmt_tag;         // Identifies way data is stored, 1 means no compression
+		int16_t fmt_channels;    // Channel, 1 means mono, 2 means stereo
+		int32_t fmt_sample_rate; // Samples per second
+		int32_t fmt_avarage;     // Avarage bytes per sample
+		int16_t fmt_block_align; // Block alignment
+		int16_t fmt_bits_ps;     // Number of bits per sample
+		char    data[4];         // Should contain 'data'
+		int32_t data_size;       // Data dimension
 	};
 
 	void compile(const char* path, CompileOptions& opts)
 	{
 		Buffer buf = opts.read(path);
-		JSONParser json(buf);
-		JSONElement root = json.root();
 
-		DynamicString name = root.key("source").to_string();
+		TempAllocator4096 ta;
+		JsonObject object(ta);
+		njson::parse(buf, object);
+
+		DynamicString name(ta);
+		njson::parse_string(object["source"], name);
 
 		Buffer sound = opts.read(name.c_str());
 		const WAVHeader* wav = (const WAVHeader*)array::begin(sound);

+ 56 - 37
src/resource/sprite_resource.cpp

@@ -6,7 +6,6 @@
 #include "allocator.h"
 #include "filesystem.h"
 #include "string_utils.h"
-#include "json_parser.h"
 #include "sprite_resource.h"
 #include "string_utils.h"
 #include "array.h"
@@ -16,6 +15,8 @@
 #include "vector4.h"
 #include "resource_manager.h"
 #include "compile_options.h"
+#include "njson.h"
+#include "map.h"
 
 namespace crown
 {
@@ -29,34 +30,41 @@ namespace sprite_resource
 		Vector2 offset;		// [Ox, Oy]
 	};
 
-	void parse_frame(JSONElement e, SpriteFrame& frame)
+	void parse_frame(const char* json, SpriteFrame& frame)
 	{
-		frame.name   = e.key("name"  ).to_string_id();
-		frame.region = e.key("region").to_vector4();
-		frame.offset = e.key("offset").to_vector2();
-		frame.scale  = e.key("scale" ).to_vector2();
+		TempAllocator512 ta;
+		JsonObject obj(ta);
+		njson::parse(json, obj);
+
+		frame.name   = njson::parse_string_id(obj["name"]);
+		frame.region = njson::parse_vector4(obj["region"]);
+		frame.offset = njson::parse_vector2(obj["offset"]);
+		frame.scale  = njson::parse_vector2(obj["scale"]);
 	}
 
 	void compile(const char* path, CompileOptions& opts)
 	{
 		Buffer buf = opts.read(path);
-		JSONParser json(buf);
-		JSONElement root = json.root();
+
+		TempAllocator4096 ta;
+		JsonObject object(ta);
+		njson::parse(buf, object);
+
+		JsonArray frames(ta);
+		njson::parse_array(object["frames"], frames);
 
 		// Read width/height
-		const float width  = root.key("width" ).to_float();
-		const float height = root.key("height").to_float();
-		const uint32_t num_frames = root.key("frames").size();
+		const float width         = parse_float(object["width" ]);
+		const float height        = parse_float(object["height"]);
+		const uint32_t num_frames = array::size(frames);
 
 		Array<float> vertices(default_allocator());
 		Array<uint16_t> indices(default_allocator());
 		uint32_t num_idx = 0;
-		for (uint32_t i = 0; i < num_frames; i++)
+		for (uint32_t i = 0; i < num_frames; ++i)
 		{
-			JSONElement e(root.key("frames")[i]);
-
 			SpriteFrame frame;
-			parse_frame(e, frame);
+			parse_frame(frames[i], frame);
 
 			const SpriteFrame& fd = frame;
 
@@ -95,7 +103,7 @@ namespace sprite_resource
 		const uint32_t num_vertices = array::size(vertices) / 4; // 4 components per vertex
 		const uint32_t num_indices = array::size(indices);
 
-		// Write header
+		// Write
 		opts.write(SPRITE_VERSION);
 
 		opts.write(num_vertices);
@@ -165,42 +173,53 @@ namespace sprite_resource
 
 namespace sprite_animation_resource
 {
-	void parse_animations(JSONElement e, Array<SpriteAnimationName>& names, Array<SpriteAnimationData>& anim_data, Array<uint32_t>& frames)
+	void parse_animation(const char* json, Array<SpriteAnimationName>& names, Array<SpriteAnimationData>& anim_data, Array<uint32_t>& frames)
 	{
-		const uint32_t num = e.key("animations").size();
-		for (uint32_t i = 0; i < num; i++)
-		{
-			JSONElement anim(e.key("animations")[i]);
+		TempAllocator512 ta;
+		JsonObject obj(ta);
+		njson::parse(json, obj);
 
-			SpriteAnimationName san;
-			san.id = anim.key("name").to_string_id();
+		SpriteAnimationName san;
+		san.id = njson::parse_string_id(obj["name"]);
 
-			const uint32_t num_frames = anim.key("frames").size();
-			SpriteAnimationData sad;
-			sad.num_frames = num_frames;
-			sad.first_frame = array::size(frames);
-			sad.time = anim.key("time").to_float();
+		JsonArray obj_frames(ta);
+		njson::parse_array(obj["frames"], obj_frames);
 
-			// Read frames
-			for (uint32_t ff = 0; ff < num_frames; ff++)
-				array::push_back(frames, (uint32_t) anim.key("frames")[ff].to_int());
+		const uint32_t num_frames = array::size(obj_frames);
 
-			array::push_back(names, san);
-			array::push_back(anim_data, sad);
-		}
+		SpriteAnimationData sad;
+		sad.num_frames  = num_frames;
+		sad.first_frame = array::size(frames);
+		sad.time        = njson::parse_float(obj["time"]);
+
+		// Read frames
+		for (uint32_t ff = 0; ff < num_frames; ++ff)
+			array::push_back(frames, (uint32_t)njson::parse_int(obj_frames[ff]));
+
+		array::push_back(names, san);
+		array::push_back(anim_data, sad);
 	}
 
 	void compile(const char* path, CompileOptions& opts)
 	{
 		Buffer buf = opts.read(path);
-		JSONParser json(buf);
-		JSONElement root = json.root();
+
+		TempAllocator4096 ta;
+		JsonObject object(ta);
+		njson::parse(buf, object);
+
+		JsonArray animations(ta);
+		njson::parse_array(object["animations"], animations);
 
 		Array<SpriteAnimationName> anim_names(default_allocator());
 		Array<SpriteAnimationData> anim_data(default_allocator());
 		Array<uint32_t> anim_frames(default_allocator());
 
-		parse_animations(root, anim_names, anim_data, anim_frames);
+		const uint32_t num_animations = array::size(animations);
+		for (uint32_t i = 0; i < num_animations; ++i)
+		{
+			parse_animation(animations[i], anim_names, anim_data, anim_frames);
+		}
 
 		SpriteAnimationResource sar;
 		sar.version = SPRITE_ANIMATION_VERSION;

+ 8 - 4
src/resource/texture_resource.cpp

@@ -6,11 +6,12 @@
 #include "filesystem.h"
 #include "texture_resource.h"
 #include "reader_writer.h"
-#include "json_parser.h"
 #include "math_utils.h"
 #include "resource_manager.h"
 #include "log.h"
 #include "compile_options.h"
+#include "njson.h"
+#include "map.h"
 #include <algorithm>
 
 namespace crown
@@ -560,10 +561,13 @@ namespace texture_resource
 	void compile(const char* path, CompileOptions& opts)
 	{
 		Buffer buf = opts.read(path);
-		JSONParser json(buf);
-		JSONElement root = json.root();
 
-		DynamicString name = root.key("source").to_string();
+		TempAllocator4096 ta;
+		JsonObject object(ta);
+		njson::parse(buf, object);
+
+		DynamicString name(ta);
+		njson::parse_string(object["source"], name);
 
 		File* source = opts._fs.open(name.c_str(), FileOpenMode::READ);
 		BinaryReader br(*source);