Explorar el Código

Split raw JSON parsing from high-level JSONElement/JSONParser

Daniele Bartolini hace 12 años
padre
commit
fbf644cf76

+ 1 - 0
engine/Android.mk

@@ -43,6 +43,7 @@ LOCAL_SRC_FILES :=\
 	core/filesystem/DiskFile.cpp\
 	core/filesystem/DiskFilesystem.cpp\
 \
+	core/json/JSON.cpp\
 	core/json/JSONParser.cpp\
 \
 	core/math/Color4.cpp\

+ 2 - 0
engine/CMakeLists.txt

@@ -185,10 +185,12 @@ set (FILESYSTEM_HEADERS
 )
 
 set (JSON_SRC
+	core/json/JSON.cpp
 	core/json/JSONParser.cpp
 )
 
 set (JSON_HEADERS
+	core/json/JSON.h
 	core/json/JSONParser.h
 )
 

+ 1 - 0
engine/Crown.h

@@ -92,6 +92,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Filesystem.h"
 
 // Core/Json
+#include "JSON.h"
 #include "JSONParser.h"
 
 // Core/Settings

+ 479 - 0
engine/core/json/JSON.cpp

@@ -0,0 +1,479 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "JSON.h"
+#include "List.h"
+#include "TempAllocator.h"
+#include "StringUtils.h"
+
+namespace crown
+{
+namespace json
+{
+
+//-----------------------------------------------------------------------------
+static const char* next(const char* str, const char c = 0)
+{
+	CE_ASSERT_NOT_NULL(str);
+
+	if (c && c != (*str))
+	{
+		CE_ASSERT(false, "Expected '%c' got '%c'", c, (*str));
+	}
+
+	return str + 1;
+}
+
+//-----------------------------------------------------------------------------
+static const char* skip_whites(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
+
+	while ((*ch) && (*ch) <= ' ') ch = next(ch);
+
+	return ch;
+}
+
+//-----------------------------------------------------------------------------
+static const char* skip_string(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
+
+	bool escaped = false;
+
+	if ((*ch) == '"')
+	{
+		while ((*(ch = next(ch))) != 0)
+		{
+			if ((*ch) == '"' && !escaped)
+			{
+				ch = next(ch);
+				return ch;
+			}
+			else if ((*ch) == '\\') escaped = true;
+			else escaped = false;
+		}
+	}
+
+	return ch;
+}
+
+//-----------------------------------------------------------------------------
+static const char* skip_number(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
+
+	while ((*ch) && (((*ch) >= '0' && (*ch) <= '9') ||
+			(*ch) == '-' || (*ch) == '.' || (*ch) == '+' ||
+			(*ch) == 'e' || (*ch) == 'E'))
+	{
+		ch = next(ch);
+	}
+
+	return ch;
+}
+
+//-----------------------------------------------------------------------------
+static const char* skip_object(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
+
+	uint32_t brackets = 1;
+
+	if ((*ch) == '{')
+	{
+		brackets++;
+		ch = next(ch, '{');
+
+		while ((*ch) && brackets != 1)
+		{
+			if ((*ch) == '}') brackets--;
+			else if ((*ch) == '{') brackets++;
+			ch = next(ch);
+		}
+	}
+
+	return ch;
+}
+
+//-----------------------------------------------------------------------------
+static const char* skip_array(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
+
+	uint32_t brackets = 1;
+
+	if ((*ch) == '[')
+	{
+		brackets++;
+		ch = next(ch, '[');
+
+		while ((*ch) && brackets != 1)
+		{
+			if ((*ch) == ']') brackets--;
+			else if ((*ch) == '[') brackets++;
+			ch = next(ch);
+		}
+	}
+
+	return ch;
+}
+
+//-----------------------------------------------------------------------------
+static const char* skip_bool(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
+
+	switch ((*ch))
+	{
+		case 't':
+		{
+			ch = next(ch, 't');
+			ch = next(ch, 'r');
+			ch = next(ch, 'u');
+			ch = next(ch, 'e');
+			break;
+		}
+		case 'f':
+		{
+			ch = next(ch, 'f');
+			ch = next(ch, 'a');
+			ch = next(ch, 'l');
+			ch = next(ch, 's');
+			ch = next(ch, 'e');
+			break;
+		}
+		default:
+		{
+			break;
+		}
+	}
+
+	return ch;
+}
+
+//-----------------------------------------------------------------------------
+static bool is_escapee(char c)
+{
+	return c == '"' || c == '\\' || c == '/' || c == '\b' || c == '\f' || c == '\n' ||
+			c == '\r' || c == '\t';
+}
+
+//-----------------------------------------------------------------------------
+JSONType::Enum type(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	const char c = s[0];
+
+	switch (c)
+	{
+		case '{': return JSONType::OBJECT;
+		case '[': return JSONType::ARRAY;
+		case '"': return JSONType::STRING;
+		case '-': return JSONType::NUMBER;
+		default: return (c >= '0' && c <= '9') ? JSONType::NUMBER : (c == 'n' ? JSONType::NIL : JSONType::BOOL);
+	}
+}
+
+//-----------------------------------------------------------------------------
+void parse_string(const char* s, List<char>& str)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
+
+	if ((*ch) == '"')
+	{
+		while ((*(ch = next(ch))))
+		{
+			// Empty string
+			if ((*ch) == '"')
+			{
+				ch = next(ch);
+				str.push_back('\0');
+				return;
+			}
+			else if ((*ch) == '\\')
+			{
+				ch = next(ch);
+
+				if ((*ch) == 'u')
+				{
+					CE_FATAL("Not supported at the moment");
+				}
+				else if (is_escapee(*ch))
+				{
+					str.push_back(*ch);
+				}
+				else
+				{
+					// Go to invalid string
+					break;
+				}
+			}
+			else
+			{
+				str.push_back(*ch);
+			}
+		}
+	}
+
+	CE_FATAL("Bad string");
+}
+
+//-----------------------------------------------------------------------------
+double parse_number(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
+
+	TempAllocator1024 allocator;
+ 	List<char> str(allocator);
+
+	if ((*ch) == '-')
+	{
+		str.push_back('-');
+		ch = next(ch, '-');
+	}
+	while ((*ch) >= '0' && (*ch) <= '9')
+	{
+		str.push_back((*ch));
+		ch = next(ch);
+	}
+
+	if ((*ch) == '.')
+	{
+		str.push_back('.');
+		while ((*(ch = next(ch))) && (*ch) >= '0' && (*ch) <= '9')
+		{
+			str.push_back(*ch);
+		}
+	}
+
+	if ((*ch) == 'e' || (*ch) == 'E')
+	{
+		str.push_back(*ch);
+		ch = next(ch);
+
+		if ((*ch) == '-' || (*ch) == '+')
+		{
+			str.push_back(*ch);
+			ch = next(ch);
+		}
+		while ((*ch) >= '0' && (*ch) <= '9')
+		{
+			str.push_back(*ch);
+			ch = next(ch);
+		}
+	}
+
+	// Ensure null terminated
+	str.push_back('\0');
+
+	return string::parse_double(str.begin());
+}
+
+//-----------------------------------------------------------------------------
+bool parse_bool(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
+
+	switch(*ch)
+	{
+		case 't':
+		{
+			ch = next(ch, 't');
+			ch = next(ch, 'r');
+			ch = next(ch, 'u');
+			ch = next(ch, 'e');
+			return true;
+		}
+		case 'f':
+		{
+			ch = next(ch, 'f');
+			ch = next(ch, 'a');
+			ch = next(ch, 'l');
+			ch = next(ch, 's');			
+			ch = next(ch, 'e');
+			return false;
+		}
+		default:
+		{
+			CE_FATAL("Bad boolean");
+			return false;
+		}
+	}
+}
+
+//-----------------------------------------------------------------------------
+int32_t parse_int(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	return (int32_t) parse_number(s);
+}
+
+//-----------------------------------------------------------------------------
+float parse_float(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	return (float) parse_number(s);
+}
+
+//-----------------------------------------------------------------------------
+void parse_array(const char* s, List<const char*>& array)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
+
+	if ((*ch) == '[')
+	{
+		ch = next(ch, '[');
+
+		// Skip whitespaces
+		while ((*ch) && (*ch) <= ' ')
+		{
+			ch = next(ch);
+		}
+
+		if ((*ch) == ']')
+		{
+			ch = next(ch, ']');
+			return;
+		}
+
+		while (*ch)
+		{
+			array.push_back(ch);
+
+			ch = skip_array(ch);
+			ch = skip_object(ch);
+			ch = skip_number(ch);
+			ch = skip_string(ch);
+			ch = skip_bool(ch);
+
+			ch = skip_whites(ch);
+
+			// Closing bracket (top-most array)
+			if ((*ch) == ']')
+			{
+				ch = next(ch, ']');
+				return;
+			}
+
+			// Skip until next ','
+			ch = next(ch, ',');
+
+			// Skip whites, eventually
+			ch = skip_whites(ch);
+		}
+	}
+
+	CE_FATAL("Bad array");
+}
+
+//-----------------------------------------------------------------------------
+void parse_object(const char* s, List<JSONPair>& object)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
+
+	if ((*ch) == '{')
+	{
+		ch = next(ch, '{');
+
+		ch = skip_whites(ch);
+
+		if ((*ch) == '}')
+		{
+			next(ch, '}');
+			return;
+		}
+
+		while (*ch)
+		{
+			JSONPair pair;
+
+			pair.key = ch;
+
+			// Skip any value
+			ch = skip_array(ch);
+			ch = skip_object(ch);
+			ch = skip_number(ch);
+			ch = skip_string(ch);
+			ch = skip_bool(ch);
+
+			ch = skip_whites(ch);
+			ch = next(ch, ':');
+			ch = skip_whites(ch);
+
+			pair.val = ch;
+			object.push_back(pair);
+
+			// Skip any value
+			ch = skip_array(ch);
+			ch = skip_object(ch);
+			ch = skip_number(ch);
+			ch = skip_string(ch);
+			ch = skip_bool(ch);
+
+			ch = skip_whites(ch);
+
+			if ((*ch) == '}')
+			{
+				next(ch, '}');
+				return;
+			}
+
+			ch = next(ch, ',');
+			ch = skip_whites(ch);
+		}
+	}
+
+	CE_FATAL("Bad object");
+}
+
+} // namespace json
+} // namespace crown

+ 89 - 0
engine/core/json/JSON.h

@@ -0,0 +1,89 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "Types.h"
+
+#pragma once
+
+namespace crown
+{
+
+template<typename T>
+class List;
+
+namespace json
+{
+
+/// Enumerates JSON value types.
+struct JSONType
+{
+	enum Enum
+	{
+		OBJECT,
+		ARRAY,
+		STRING,
+		NUMBER,
+		BOOL,
+		NIL
+	};
+};
+
+/// Represents a key-value pair in a JSON document.
+struct JSONPair
+{
+	const char* key;
+	const char* val;
+};
+
+
+/// Returns the type of the @a s JSON text. 
+JSONType::Enum type(const char* s);
+
+/// Parses the @a s JSON string a puts its C representation into @a str.
+void parse_string(const char* s, List<char>& str);
+
+/// Returns the value of the @a s JSON number as double.
+double parse_number(const char* s);
+
+/// Returns the value of the @a s JSON boolean.
+bool parse_bool(const char* s);
+
+/// Returns the value of the @a s JSON number as signed integer.
+int32_t parse_int(const char* s);
+
+/// Returns the value of the @a s JSON number as float.
+float parse_float(const char* s);
+
+/// Parses the @a s JSON array and puts it into @a array as pointers to
+/// the corresponding items into the original @a s string.
+void parse_array(const char* s, List<const char*>& array);
+
+/// Parses the @a s JSON object and puts it into @a object as pointers to
+/// the corresponding key/value pairs into the original @a s string.
+void parse_object(const char* s, List<JSONPair>& object);
+
+} // namespace json
+} // namespace crown

+ 51 - 482
engine/core/json/JSONParser.cpp

@@ -25,6 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #include "JSONParser.h"
+#include "JSON.h"
 #include "TempAllocator.h"
 #include "StringUtils.h"
 #include "Log.h"
@@ -32,165 +33,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
-//-----------------------------------------------------------------------------
-static const char* next(const char* str, const char c = 0)
-{
-	CE_ASSERT_NOT_NULL(str);
-
-	if (c && c != (*str))
-	{
-		CE_ASSERT(false, "Expected '%c' got '%c'", c, (*str));
-	}
-
-	return str + 1;
-}
-
-//-----------------------------------------------------------------------------
-static const char* skip_whites(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	const char* ch = s;
-
-	while ((*ch) && (*ch) <= ' ') ch = next(ch);
-
-	return ch;
-}
-
-//-----------------------------------------------------------------------------
-static const char* skip_string(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	const char* ch = s;
-
-	bool escaped = false;
-
-	if ((*ch) == '"')
-	{
-		while ((*(ch = next(ch))) != 0)
-		{
-			if ((*ch) == '"' && !escaped)
-			{
-				ch = next(ch);
-				return ch;
-			}
-			else if ((*ch) == '\\') escaped = true;
-			else escaped = false;
-		}
-	}
-
-	return ch;
-}
-
-//-----------------------------------------------------------------------------
-static const char* skip_number(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	const char* ch = s;
-
-	while ((*ch) && (((*ch) >= '0' && (*ch) <= '9') ||
-			(*ch) == '-' || (*ch) == '.' || (*ch) == '+' ||
-			(*ch) == 'e' || (*ch) == 'E'))
-	{
-		ch = next(ch);
-	}
-
-	return ch;
-}
-
-//-----------------------------------------------------------------------------
-static const char* skip_object(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	const char* ch = s;
-
-	uint32_t brackets = 1;
-
-	if ((*ch) == '{')
-	{
-		brackets++;
-		ch = next(ch, '{');
-
-		while ((*ch) && brackets != 1)
-		{
-			if ((*ch) == '}') brackets--;
-			else if ((*ch) == '{') brackets++;
-			ch = next(ch);
-		}
-	}
-
-	return ch;
-}
-
-//-----------------------------------------------------------------------------
-static const char* skip_array(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	const char* ch = s;
-
-	uint32_t brackets = 1;
-
-	if ((*ch) == '[')
-	{
-		brackets++;
-		ch = next(ch, '[');
-
-		while ((*ch) && brackets != 1)
-		{
-			if ((*ch) == ']') brackets--;
-			else if ((*ch) == '[') brackets++;
-			ch = next(ch);
-		}
-	}
-
-	return ch;
-}
-
-//-----------------------------------------------------------------------------
-static const char* skip_bool(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	const char* ch = s;
-
-	switch ((*ch))
-	{
-		case 't':
-		{
-			ch = next(ch, 't');
-			ch = next(ch, 'r');
-			ch = next(ch, 'u');
-			ch = next(ch, 'e');
-			break;
-		}
-		case 'f':
-		{
-			ch = next(ch, 'f');
-			ch = next(ch, 'a');
-			ch = next(ch, 'l');
-			ch = next(ch, 's');
-			ch = next(ch, 'e');
-			break;
-		}
-		default:
-		{
-			break;
-		}
-	}
-
-	return ch;
-}
-
-//-----------------------------------------------------------------------------
-static bool is_escapee(char c)
-{
-	return c == '"' || c == '\\' || c == '/' || c == '\b' || c == '\f' || c == '\n' ||
-			c == '\r' || c == '\t';
-}
+using json::JSONType;
+using json::JSONPair;
 
 //--------------------------------------------------------------------------
 JSONElement::JSONElement()
@@ -225,7 +69,7 @@ JSONElement JSONElement::operator[](uint32_t i)
 	TempAllocator1024 alloc;
 	List<const char*> array(alloc);
 
-	JSONParser::parse_array(m_at, array);
+	json::parse_array(m_at, array);
 
 	CE_ASSERT(i < array.size(), "Index out of bounds");
 
@@ -246,7 +90,7 @@ JSONElement JSONElement::index_or_nil(uint32_t i)
 		TempAllocator1024 alloc;
 		List<const char*> array(alloc);
 
-		JSONParser::parse_array(m_at, array);
+		json::parse_array(m_at, array);
 
 		if (i >= array.size())
 		{
@@ -265,7 +109,7 @@ JSONElement JSONElement::key(const char* k)
 	TempAllocator1024 alloc;
 	List<JSONPair> object(alloc);
 
-	JSONParser::parse_object(m_at, object);
+	json::parse_object(m_at, object);
 
 	bool found = false;
 
@@ -275,7 +119,7 @@ JSONElement JSONElement::key(const char* k)
 		TempAllocator256 key_alloc;
 		List<char> key(key_alloc);
 
-		JSONParser::parse_string(object[i].key, key);
+		json::parse_string(object[i].key, key);
 
 		if (string::strcmp(k, key.begin()) == 0)
 		{
@@ -297,7 +141,7 @@ JSONElement JSONElement::key_or_nil(const char* k)
 		TempAllocator1024 alloc;
 		List<JSONPair> object(alloc);
 
-		JSONParser::parse_object(m_at, object);
+		json::parse_object(m_at, object);
 
 		bool found = false;
 
@@ -307,7 +151,7 @@ JSONElement JSONElement::key_or_nil(const char* k)
 			TempAllocator256 key_alloc;
 			List<char> key(key_alloc);
 
-			JSONParser::parse_string(object[i].key, key);
+			json::parse_string(object[i].key, key);
 
 			if (string::strcmp(k, key.begin()) == 0)
 			{
@@ -332,14 +176,14 @@ bool JSONElement::has_key(const char* k) const
 {
 	TempAllocator1024 alloc;
 	List<JSONPair> object(alloc);
-	JSONParser::parse_object(m_at, object);
+	json::parse_object(m_at, object);
 
 	for (uint32_t i = 0; i < object.size(); i++)
 	{
 		TempAllocator256 key_alloc;
 		List<char> key(key_alloc);
 
-		JSONParser::parse_string(object[i].key, key);
+		json::parse_string(object[i].key, key);
 
 		if (string::strcmp(k, key.begin()) == 0)
 		{
@@ -355,7 +199,7 @@ bool JSONElement::is_key_unique(const char* k) const
 {
 	TempAllocator1024 alloc;
 	List<JSONPair> object(alloc);
-	JSONParser::parse_object(m_at, object);
+	json::parse_object(m_at, object);
 
 	bool found = false;
 
@@ -364,7 +208,7 @@ bool JSONElement::is_key_unique(const char* k) const
 		TempAllocator256 key_alloc;
 		List<char> key(key_alloc);
 
-		JSONParser::parse_string(object[i].key, key);
+		json::parse_string(object[i].key, key);
 
 		if (string::strcmp(k, key.begin()) == 0)
 		{
@@ -383,21 +227,21 @@ bool JSONElement::is_key_unique(const char* k) const
 //--------------------------------------------------------------------------
 bool JSONElement::bool_value() const
 {
-	const bool value = JSONParser::parse_bool(m_at);
+	const bool value = json::parse_bool(m_at);
 	return value;
 }
 
 //--------------------------------------------------------------------------
 int32_t JSONElement::int_value() const
 {
-	const int32_t value = JSONParser::parse_int(m_at);
+	const int32_t value = json::parse_int(m_at);
 	return value;
 }
 
 //--------------------------------------------------------------------------
 float JSONElement::float_value() const
 {
-	const float value = JSONParser::parse_float(m_at);
+	const float value = json::parse_float(m_at);
 	return value;
 }
 
@@ -409,7 +253,7 @@ const char* JSONElement::string_value() const
 
 	string.clear();
 
-	JSONParser::parse_string(m_at, string);
+	json::parse_string(m_at, string);
 
 	return string.begin();
 }
@@ -420,11 +264,11 @@ void JSONElement::array_value(List<bool>& array) const
 	TempAllocator1024 alloc;
 	List<const char*> temp(alloc);
 
-	JSONParser::parse_array(m_at, temp);
+	json::parse_array(m_at, temp);
 
 	for (uint32_t i = 0; i < temp.size(); i++)
 	{
-		array.push_back(JSONParser::parse_bool(temp[i]));
+		array.push_back(json::parse_bool(temp[i]));
 	}
 }
 
@@ -434,11 +278,11 @@ void JSONElement::array_value(List<int16_t>& array) const
 	TempAllocator1024 alloc;
 	List<const char*> temp(alloc);
 
-	JSONParser::parse_array(m_at, temp);
+	json::parse_array(m_at, temp);
 
 	for (uint32_t i = 0; i < temp.size(); i++)
 	{
-		array.push_back((int16_t)JSONParser::parse_int(temp[i]));
+		array.push_back((int16_t)json::parse_int(temp[i]));
 	}
 }
 
@@ -448,11 +292,11 @@ void JSONElement::array_value(List<uint16_t>& array) const
 	TempAllocator1024 alloc;
 	List<const char*> temp(alloc);
 
-	JSONParser::parse_array(m_at, temp);
+	json::parse_array(m_at, temp);
 
 	for (uint32_t i = 0; i < temp.size(); i++)
 	{
-		array.push_back((uint16_t)JSONParser::parse_int(temp[i]));
+		array.push_back((uint16_t)json::parse_int(temp[i]));
 	}
 }
 
@@ -462,11 +306,11 @@ void JSONElement::array_value(List<int32_t>& array) const
 	TempAllocator1024 alloc;
 	List<const char*> temp(alloc);
 
-	JSONParser::parse_array(m_at, temp);
+	json::parse_array(m_at, temp);
 
 	for (uint32_t i = 0; i < temp.size(); i++)
 	{
-		array.push_back((int32_t)JSONParser::parse_int(temp[i]));
+		array.push_back((int32_t)json::parse_int(temp[i]));
 	}
 }
 
@@ -476,11 +320,11 @@ void JSONElement::array_value(List<uint32_t>& array) const
 	TempAllocator1024 alloc;
 	List<const char*> temp(alloc);
 
-	JSONParser::parse_array(m_at, temp);
+	json::parse_array(m_at, temp);
 
 	for (uint32_t i = 0; i < temp.size(); i++)
 	{
-		array.push_back((uint32_t)JSONParser::parse_int(temp[i]));
+		array.push_back((uint32_t)json::parse_int(temp[i]));
 	}
 }
 
@@ -490,11 +334,11 @@ void JSONElement::array_value(List<float>& array) const
 	TempAllocator1024 alloc;
 	List<const char*> temp(alloc);
 
-	JSONParser::parse_array(m_at, temp);
+	json::parse_array(m_at, temp);
 
 	for (uint32_t i = 0; i < temp.size(); i++)
 	{
-		array.push_back(JSONParser::parse_float(temp[i]));
+		array.push_back(json::parse_float(temp[i]));
 	}
 }
 
@@ -503,7 +347,7 @@ bool JSONElement::is_nil() const
 {
 	if (m_at != NULL)
 	{
-		return JSONParser::type(m_at) == JT_NIL;
+		return json::type(m_at) == JSONType::NIL;
 	}
 
 	return true;
@@ -514,7 +358,7 @@ bool JSONElement::is_bool() const
 {
 	if (m_at != NULL)
 	{
-		return JSONParser::type(m_at) == JT_BOOL;
+		return json::type(m_at) == JSONType::BOOL;
 	}
 
 	return false;
@@ -525,7 +369,7 @@ bool JSONElement::is_number() const
 {
 	if (m_at != NULL)
 	{
-		return JSONParser::type(m_at) == JT_NUMBER;		
+		return json::type(m_at) == JSONType::NUMBER;		
 	}
 
 	return false;
@@ -536,7 +380,7 @@ bool JSONElement::is_string() const
 {
 	if (m_at != NULL)
 	{
-		return JSONParser::type(m_at) == JT_STRING;
+		return json::type(m_at) == JSONType::STRING;
 	}
 
 	return false;
@@ -547,7 +391,7 @@ bool JSONElement::is_array() const
 {
 	if (m_at != NULL)
 	{
-		return JSONParser::type(m_at) == JT_ARRAY;
+		return json::type(m_at) == JSONType::ARRAY;
 	}
 
 	return false;
@@ -558,7 +402,7 @@ bool JSONElement::is_object() const
 {
 	if (m_at != NULL)
 	{
-		return JSONParser::type(m_at) == JT_OBJECT;
+		return json::type(m_at) == JSONType::OBJECT;
 	}
 
 	return false;
@@ -572,54 +416,55 @@ uint32_t JSONElement::size() const
 		return 0;
 	}
 
-	switch(JSONParser::type(m_at))
+	switch(json::type(m_at))
 	{
-		case JT_NIL:
+		case JSONType::NIL:
 		{
 			return 1;
 		}
-		case JT_OBJECT:
+		case JSONType::OBJECT:
 		{
 			TempAllocator1024 alloc;
 			List<JSONPair> object(alloc);
-			JSONParser::parse_object(m_at, object);
+			json::parse_object(m_at, object);
 
 			return object.size();
 		}
-		case JT_ARRAY:
+		case JSONType::ARRAY:
 		{
 			TempAllocator1024 alloc;
 			List<const char*> array(alloc);
-			JSONParser::parse_array(m_at, array);
+			json::parse_array(m_at, array);
 
 			return array.size();
 		}
-		case JT_STRING:
+		case JSONType::STRING:
 		{
 			TempAllocator1024 alloc;
 			List<char> string(alloc);
-			JSONParser::parse_string(m_at, string);
+			json::parse_string(m_at, string);
 
 			return string::strlen(string.begin());
 		}
-		case JT_NUMBER:
+		case JSONType::NUMBER:
 		{
 			return 1;
 		}
-		case JT_BOOL:
+		case JSONType::BOOL:
 		{
 			return 1;
 		}
 		default:
 		{
+			CE_FATAL("Oops, unknown value type");
 			return 0;
 		}
 	}
 }
 
 //--------------------------------------------------------------------------
-JSONParser::JSONParser(const char* s) :
-	m_document(s)
+JSONParser::JSONParser(const char* s)
+	: m_document(s)
 {
 	CE_ASSERT_NOT_NULL(s);
 }
@@ -627,286 +472,10 @@ JSONParser::JSONParser(const char* s) :
 //--------------------------------------------------------------------------
 JSONElement JSONParser::root()
 {
-	return JSONElement(skip_whites(m_document));
-}
-
-//-----------------------------------------------------------------------------
-JSONType JSONParser::type(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	switch (s[0])
-	{
-		case '{': return JT_OBJECT;
-		case '[': return JT_ARRAY;
-		case '"': return JT_STRING;
-		case '-': return JT_NUMBER;
-		default: return s[0] >= '0' && s[0] <= '9' ? JT_NUMBER : (s[0] == 'n' ? JT_NIL : JT_BOOL);
-	}
-}
-
-//-----------------------------------------------------------------------------
-void JSONParser::parse_string(const char* s, List<char>& str)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	const char* ch = s;
-
-	if ((*ch) == '"')
-	{
-		while ((*(ch = next(ch))))
-		{
-			// Empty string
-			if ((*ch) == '"')
-			{
-				ch = next(ch);
-				str.push_back('\0');
-				return;
-			}
-			else if ((*ch) == '\\')
-			{
-				ch = next(ch);
-
-				if ((*ch) == 'u')
-				{
-					CE_ASSERT(false, "Not supported at the moment");
-				}
-				else if (is_escapee(*ch))
-				{
-					str.push_back(*ch);
-				}
-				else
-				{
-					// Go to invalid string
-					break;
-				}
-			}
-			else
-			{
-				str.push_back(*ch);
-			}
-		}
-	}
-
-	CE_ASSERT(false, "Bad string");
-}
-
-//-----------------------------------------------------------------------------
-double JSONParser::parse_number(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	const char* ch = s;
-
-	TempAllocator1024 allocator;
- 	List<char> str(allocator);
-
-	if ((*ch) == '-')
-	{
-		str.push_back('-');
-		ch = next(ch, '-');
-	}
-	while ((*ch) >= '0' && (*ch) <= '9')
-	{
-		str.push_back((*ch));
-		ch = next(ch);
-	}
-
-	if ((*ch) == '.')
-	{
-		str.push_back('.');
-		while ((*(ch = next(ch))) && (*ch) >= '0' && (*ch) <= '9')
-		{
-			str.push_back(*ch);
-		}
-	}
-
-	if ((*ch) == 'e' || (*ch) == 'E')
-	{
-		str.push_back(*ch);
-		ch = next(ch);
-
-		if ((*ch) == '-' || (*ch) == '+')
-		{
-			str.push_back(*ch);
-			ch = next(ch);
-		}
-		while ((*ch) >= '0' && (*ch) <= '9')
-		{
-			str.push_back(*ch);
-			ch = next(ch);
-		}
-	}
-
-	// Ensure null terminated
-	str.push_back('\0');
-
-	return string::parse_double(str.begin());
-}
-
-//-----------------------------------------------------------------------------
-bool JSONParser::parse_bool(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	const char* ch = s;
-
-	switch(*ch)
-	{
-		case 't':
-		{
-			ch = next(ch, 't');
-			ch = next(ch, 'r');
-			ch = next(ch, 'u');
-			ch = next(ch, 'e');
-			return true;
-		}
-		case 'f':
-		{
-			ch = next(ch, 'f');
-			ch = next(ch, 'a');
-			ch = next(ch, 'l');
-			ch = next(ch, 's');			
-			ch = next(ch, 'e');
-			return false;
-		}
-		default:
-		{
-			CE_ASSERT(false, "Bad boolean");
-			return false;
-		}
-	}
-}
-
-//-----------------------------------------------------------------------------
-int32_t JSONParser::parse_int(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	return (int32_t) parse_number(s);
-}
-
-//-----------------------------------------------------------------------------
-float JSONParser::parse_float(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	return (float) parse_number(s);
-}
-
-//-----------------------------------------------------------------------------
-void JSONParser::parse_array(const char* s, List<const char*>& array)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	const char* ch = s;
-
-	if ((*ch) == '[')
-	{
-		ch = next(ch, '[');
-
-		// Skip whitespaces
-		while ((*ch) && (*ch) <= ' ')
-		{
-			ch = next(ch);
-		}
-
-		if ((*ch) == ']')
-		{
-			ch = next(ch, ']');
-			return;
-		}
-
-		while (*ch)
-		{
-			array.push_back(ch);
-
-			ch = skip_array(ch);
-			ch = skip_object(ch);
-			ch = skip_number(ch);
-			ch = skip_string(ch);
-			ch = skip_bool(ch);
-
-			ch = skip_whites(ch);
-
-			// Closing bracket (top-most array)
-			if ((*ch) == ']')
-			{
-				ch = next(ch, ']');
-				return;
-			}
-
-			// Skip until next ','
-			ch = next(ch, ',');
-
-			// Skip whites, eventually
-			ch = skip_whites(ch);
-		}
-	}
-
-	CE_ASSERT(false, "Bad array");
-}
-
-//-----------------------------------------------------------------------------
-void JSONParser::parse_object(const char* s, List<JSONPair>& object)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	const char* ch = s;
-
-	if ((*ch) == '{')
-	{
-		ch = next(ch, '{');
-
-		ch = skip_whites(ch);
-
-		if ((*ch) == '}')
-		{
-			next(ch, '}');
-			return;
-		}
-
-		while (*ch)
-		{
-			JSONPair pair;
-
-			pair.key = ch;
-
-			// Skip any value
-			ch = skip_array(ch);
-			ch = skip_object(ch);
-			ch = skip_number(ch);
-			ch = skip_string(ch);
-			ch = skip_bool(ch);
-
-			ch = skip_whites(ch);
-			ch = next(ch, ':');
-			ch = skip_whites(ch);
-
-			pair.val = ch;
-			object.push_back(pair);
-
-			// Skip any value
-			ch = skip_array(ch);
-			ch = skip_object(ch);
-			ch = skip_number(ch);
-			ch = skip_string(ch);
-			ch = skip_bool(ch);
-
-			ch = skip_whites(ch);
-
-			if ((*ch) == '}')
-			{
-				next(ch, '}');
-				return;
-			}
-
-			ch = next(ch, ',');
-			ch = skip_whites(ch);
-		}
-	}
+	const char* ch = m_document;
+	while ((*ch) && (*ch) <= ' ') ch++;
 
-	CE_ASSERT(false, "Bad object");
+	return JSONElement(ch);
 }
 
 } //namespace crown

+ 0 - 45
engine/core/json/JSONParser.h

@@ -32,23 +32,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
-enum JSONType
-{
-	JT_NIL,
-	JT_OBJECT,
-	JT_ARRAY,
-	JT_STRING,
-	JT_NUMBER,
-	JT_BOOL
-};
-
-/// Represents a key-value pair in a JSON document.
-struct JSONPair
-{
-	const char* key;
-	const char* val;
-};
-
 class JSONParser;
 
 /// Represents a JSON element.
@@ -181,34 +164,6 @@ public:
 	/// Returns the root element of the JSON document.
 	JSONElement			root();
 
-public:
-
-	/// Returns the type of the @a s JSON text. 
-	static JSONType		type(const char* s);
-
-	/// Parses the @a s JSON string a puts its C representation into @a str.
-	static void			parse_string(const char* s, List<char>& str);
-
-	/// Returns the value of the @a s JSON number as double.
-	static double		parse_number(const char* s);
-
-	/// Returns the value of the @a s JSON boolean.
-	static bool			parse_bool(const char* s);
-
-	/// Returns the value of the @a s JSON number as signed integer.
-	static int32_t 		parse_int(const char* s);
-
-	/// Returns the value of the @a s JSON number as float.
-	static float		parse_float(const char* s);
-
-	/// Parses the @a s JSON array and puts it into @a array as pointers to
-	/// the corresponding items into the original @a s string.
-	static void			parse_array(const char* s, List<const char*>& array);
-
-	/// Parses the @a s JSON object and puts it into @a object as pointers to
-	/// the corresponding key/value pairs into the original @a s string.
-	static void			parse_object(const char* s, List<JSONPair>& object);
-
 private:
 
 	const char* const	m_document;