Procházet zdrojové kódy

Adjust core/json formatting and update json::* documentation

Daniele Bartolini před 12 roky
rodič
revize
a53d45de04
3 změnil soubory, kde provedl 355 přidání a 366 odebrání
  1. 332 334
      engine/core/json/JSON.cpp
  2. 23 29
      engine/core/json/JSON.h
  3. 0 3
      engine/core/json/JSONParser.cpp

+ 332 - 334
engine/core/json/JSON.cpp

@@ -33,449 +33,411 @@ namespace crown
 {
 namespace json
 {
+	//-----------------------------------------------------------------------------
+	static const char* next(const char* str, const char c = 0)
+	{
+		CE_ASSERT_NOT_NULL(str);
 
-//-----------------------------------------------------------------------------
-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));
+		}
 
-	if (c && c != (*str))
-	{
-		CE_ASSERT(false, "Expected '%c' got '%c'", c, (*str));
+		return str + 1;
 	}
 
-	return str + 1;
-}
-
-//-----------------------------------------------------------------------------
-static const char* skip_whites(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
+	//-----------------------------------------------------------------------------
+	static const char* skip_whites(const char* s)
+	{
+		CE_ASSERT_NOT_NULL(s);
 
-	const char* ch = s;
+		const char* ch = s;
 
-	while ((*ch) && (*ch) <= ' ') ch = next(ch);
+		while ((*ch) && (*ch) <= ' ') ch = next(ch);
 
-	return ch;
-}
+		return ch;
+	}
 
-//-----------------------------------------------------------------------------
-static const char* skip_string(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
+	//-----------------------------------------------------------------------------
+	static const char* skip_string(const char* s)
+	{
+		CE_ASSERT_NOT_NULL(s);
 
-	const char* ch = s;
+		const char* ch = s;
 
-	bool escaped = false;
+		bool escaped = false;
 
-	if ((*ch) == '"')
-	{
-		while ((*(ch = next(ch))) != 0)
+		if ((*ch) == '"')
 		{
-			if ((*ch) == '"' && !escaped)
+			while ((*(ch = next(ch))) != 0)
 			{
-				ch = next(ch);
-				return ch;
+				if ((*ch) == '"' && !escaped)
+				{
+					ch = next(ch);
+					return ch;
+				}
+				else if ((*ch) == '\\') escaped = true;
+				else escaped = false;
 			}
-			else if ((*ch) == '\\') escaped = true;
-			else escaped = false;
 		}
+
+		return ch;
 	}
 
-	return ch;
-}
+	//-----------------------------------------------------------------------------
+	static const char* skip_number(const char* s)
+	{
+		CE_ASSERT_NOT_NULL(s);
 
-//-----------------------------------------------------------------------------
-static const char* skip_number(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
+		const char* ch = s;
 
-	const char* ch = s;
+		while ((*ch) && (((*ch) >= '0' && (*ch) <= '9') ||
+				(*ch) == '-' || (*ch) == '.' || (*ch) == '+' ||
+				(*ch) == 'e' || (*ch) == 'E'))
+		{
+			ch = next(ch);
+		}
 
-	while ((*ch) && (((*ch) >= '0' && (*ch) <= '9') ||
-			(*ch) == '-' || (*ch) == '.' || (*ch) == '+' ||
-			(*ch) == 'e' || (*ch) == 'E'))
-	{
-		ch = next(ch);
+		return ch;
 	}
 
-	return ch;
-}
-
-//-----------------------------------------------------------------------------
-static const char* skip_object(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
-
-	const char* ch = s;
+	//-----------------------------------------------------------------------------
+	static const char* skip_object(const char* s)
+	{
+		CE_ASSERT_NOT_NULL(s);
 
-	uint32_t brackets = 1;
+		const char* ch = s;
 
-	if ((*ch) == '{')
-	{
-		brackets++;
-		ch = next(ch, '{');
+		uint32_t brackets = 1;
 
-		while ((*ch) && brackets != 1)
+		if ((*ch) == '{')
 		{
-			if ((*ch) == '}') brackets--;
-			else if ((*ch) == '{') brackets++;
-			ch = next(ch);
-		}
-	}
+			brackets++;
+			ch = next(ch, '{');
 
-	return ch;
-}
+			while ((*ch) && brackets != 1)
+			{
+				if ((*ch) == '}') brackets--;
+				else if ((*ch) == '{') brackets++;
+				ch = next(ch);
+			}
+		}
 
-//-----------------------------------------------------------------------------
-static const char* skip_array(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
+		return ch;
+	}
 
-	const char* ch = s;
+	//-----------------------------------------------------------------------------
+	static const char* skip_array(const char* s)
+	{
+		CE_ASSERT_NOT_NULL(s);
 
-	uint32_t brackets = 1;
+		const char* ch = s;
 
-	if ((*ch) == '[')
-	{
-		brackets++;
-		ch = next(ch, '[');
+		uint32_t brackets = 1;
 
-		while ((*ch) && brackets != 1)
+		if ((*ch) == '[')
 		{
-			if ((*ch) == ']') brackets--;
-			else if ((*ch) == '[') brackets++;
-			ch = next(ch);
+			brackets++;
+			ch = next(ch, '[');
+
+			while ((*ch) && brackets != 1)
+			{
+				if ((*ch) == ']') brackets--;
+				else if ((*ch) == '[') brackets++;
+				ch = next(ch);
+			}
 		}
+
+		return ch;
 	}
 
-	return ch;
-}
+	//-----------------------------------------------------------------------------
+	static const char* skip_bool(const char* s)
+	{
+		CE_ASSERT_NOT_NULL(s);
+
+		const char* ch = s;
 
-//-----------------------------------------------------------------------------
-static const char* skip_bool(const char* s)
-{
-	CE_ASSERT_NOT_NULL(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;
+			}
+		}
 
-	const char* ch = s;
+		return ch;
+	}
 
-	switch ((*ch))
+	//-----------------------------------------------------------------------------
+	static const char* skip_null(const char* s)
 	{
-		case 't':
+		CE_ASSERT_NOT_NULL(s);
+
+		const char* ch = s;
+		if ((*ch) == 'n')
 		{
-			ch = next(ch, 't');
-			ch = next(ch, 'r');
+			ch = next(ch, 'n');
 			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;
+			ch = next(ch, 'l');
 		}
-	}
 
-	return ch;
-}
-
-//-----------------------------------------------------------------------------
-static const char* skip_null(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
+		return ch;
+	}
 
-	const char* ch = s;
-	if ((*ch) == 'n')
+	//-----------------------------------------------------------------------------
+	static bool is_escapee(char c)
 	{
-		ch = next(ch, 'n');
-		ch = next(ch, 'u');
-		ch = next(ch, 'l');
-		ch = next(ch, 'l');
+		return c == '"' || c == '\\' || c == '/' || c == '\b' || c == '\f' || c == '\n' ||
+				c == '\r' || c == '\t';
 	}
 
-	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);
+	//-----------------------------------------------------------------------------
+	JSONType::Enum type(const char* s)
+	{
+		CE_ASSERT_NOT_NULL(s);
 
-	const char c = s[0];
+		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);
+		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, DynamicString& str)
-{
-	CE_ASSERT_NOT_NULL(s);
+	//-----------------------------------------------------------------------------
+	void parse_string(const char* s, DynamicString& str)
+	{
+		CE_ASSERT_NOT_NULL(s);
 
-	const char* ch = s;
+		const char* ch = s;
 
-	if ((*ch) == '"')
-	{
-		while ((*(ch = next(ch))))
+		if ((*ch) == '"')
 		{
-			// Empty string
-			if ((*ch) == '"')
-			{
-				ch = next(ch);
-				return;
-			}
-			else if ((*ch) == '\\')
+			while ((*(ch = next(ch))))
 			{
-				ch = next(ch);
-
-				if ((*ch) == 'u')
+				// Empty string
+				if ((*ch) == '"')
 				{
-					CE_FATAL("Not supported at the moment");
+					ch = next(ch);
+					return;
 				}
-				else if (is_escapee(*ch))
+				else if ((*ch) == '\\')
 				{
-					str += (*ch);
+					ch = next(ch);
+
+					if ((*ch) == 'u')
+					{
+						CE_FATAL("Not supported at the moment");
+					}
+					else if (is_escapee(*ch))
+					{
+						str += (*ch);
+					}
+					else
+					{
+						// Go to invalid string
+						break;
+					}
 				}
 				else
 				{
-					// Go to invalid string
-					break;
+					str += (*ch);
 				}
 			}
-			else
-			{
-				str += (*ch);
-			}
 		}
-	}
-
-	CE_FATAL("Bad string");
-}
 
-//-----------------------------------------------------------------------------
-double parse_number(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
+		CE_FATAL("Bad string");
+	}
 
-	const char* ch = s;
+	//-----------------------------------------------------------------------------
+	double parse_number(const char* s)
+	{
+		CE_ASSERT_NOT_NULL(s);
 
- 	Array<char> str(default_allocator());
+		const char* ch = s;
 
-	if ((*ch) == '-')
-	{
-		array::push_back(str, '-');
-		ch = next(ch, '-');
-	}
-	while ((*ch) >= '0' && (*ch) <= '9')
-	{
-		array::push_back(str, (*ch));
-		ch = next(ch);
-	}
+	 	Array<char> str(default_allocator());
 
-	if ((*ch) == '.')
-	{
-		array::push_back(str, '.');
-		while ((*(ch = next(ch))) && (*ch) >= '0' && (*ch) <= '9')
+		if ((*ch) == '-')
 		{
-			array::push_back(str, *ch);
+			array::push_back(str, '-');
+			ch = next(ch, '-');
 		}
-	}
-
-	if ((*ch) == 'e' || (*ch) == 'E')
-	{
-		array::push_back(str, *ch);
-		ch = next(ch);
-
-		if ((*ch) == '-' || (*ch) == '+')
+		while ((*ch) >= '0' && (*ch) <= '9')
 		{
-			array::push_back(str, *ch);
+			array::push_back(str, (*ch));
 			ch = next(ch);
 		}
-		while ((*ch) >= '0' && (*ch) <= '9')
+
+		if ((*ch) == '.')
+		{
+			array::push_back(str, '.');
+			while ((*(ch = next(ch))) && (*ch) >= '0' && (*ch) <= '9')
+			{
+				array::push_back(str, *ch);
+			}
+		}
+
+		if ((*ch) == 'e' || (*ch) == 'E')
 		{
 			array::push_back(str, *ch);
 			ch = next(ch);
+
+			if ((*ch) == '-' || (*ch) == '+')
+			{
+				array::push_back(str, *ch);
+				ch = next(ch);
+			}
+			while ((*ch) >= '0' && (*ch) <= '9')
+			{
+				array::push_back(str, *ch);
+				ch = next(ch);
+			}
 		}
-	}
 
-	// Ensure null terminated
-	array::push_back(str, '\0');
+		// Ensure null terminated
+		array::push_back(str, '\0');
 
-	return string::parse_double(array::begin(str));
-}
+		return string::parse_double(array::begin(str));
+	}
 
-//-----------------------------------------------------------------------------
-bool parse_bool(const char* s)
-{
-	CE_ASSERT_NOT_NULL(s);
+	//-----------------------------------------------------------------------------
+	bool parse_bool(const char* s)
+	{
+		CE_ASSERT_NOT_NULL(s);
 
-	const char* ch = 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':
+		switch(*ch)
 		{
-			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;
+			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);
+	//-----------------------------------------------------------------------------
+	int32_t parse_int(const char* s)
+	{
+		CE_ASSERT_NOT_NULL(s);
 
-	return (float) parse_number(s);
-}
+		return (int32_t) parse_number(s);
+	}
 
-//-----------------------------------------------------------------------------
-void parse_array(const char* s, Array<const char*>& array)
-{
-	CE_ASSERT_NOT_NULL(s);
+	//-----------------------------------------------------------------------------
+	float parse_float(const char* s)
+	{
+		CE_ASSERT_NOT_NULL(s);
 
-	const char* ch = s;
+		return (float) parse_number(s);
+	}
 
-	if ((*ch) == '[')
+	//-----------------------------------------------------------------------------
+	void parse_array(const char* s, Array<const char*>& array)
 	{
-		ch = next(ch, '[');
+		CE_ASSERT_NOT_NULL(s);
 
-		// Skip whitespaces
-		while ((*ch) && (*ch) <= ' ')
-		{
-			ch = next(ch);
-		}
-
-		if ((*ch) == ']')
-		{
-			ch = next(ch, ']');
-			return;
-		}
+		const char* ch = s;
 
-		while (*ch)
+		if ((*ch) == '[')
 		{
-			array::push_back(array, ch);
+			ch = next(ch, '[');
 
-			ch = skip_array(ch);
-			ch = skip_object(ch);
-			ch = skip_number(ch);
-			ch = skip_string(ch);
-			ch = skip_bool(ch);
-			ch = skip_null(ch);
-
-			ch = skip_whites(ch);
+			// Skip whitespaces
+			while ((*ch) && (*ch) <= ' ')
+			{
+				ch = next(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");
-}
+			while (*ch)
+			{
+				array::push_back(array, ch);
 
-//-----------------------------------------------------------------------------
-void parse_object(const char* s, Array<JSONPair>& object)
-{
-	CE_ASSERT_NOT_NULL(s);
+				ch = skip_array(ch);
+				ch = skip_object(ch);
+				ch = skip_number(ch);
+				ch = skip_string(ch);
+				ch = skip_bool(ch);
+				ch = skip_null(ch);
 
-	const char* ch = s;
+				ch = skip_whites(ch);
 
-	if ((*ch) == '{')
-	{
-		ch = next(ch, '{');
+				// Closing bracket (top-most array)
+				if ((*ch) == ']')
+				{
+					ch = next(ch, ']');
+					return;
+				}
 
-		ch = skip_whites(ch);
+				// Skip until next ','
+				ch = next(ch, ',');
 
-		if ((*ch) == '}')
-		{
-			next(ch, '}');
-			return;
+				// Skip whites, eventually
+				ch = skip_whites(ch);
+			}
 		}
 
-		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_null(ch);
+		CE_FATAL("Bad array");
+	}
 
-			ch = skip_whites(ch);
-			ch = next(ch, ':');
-			ch = skip_whites(ch);
+	//-----------------------------------------------------------------------------
+	void parse_object(const char* s, Array<JSONPair>& object)
+	{
+		CE_ASSERT_NOT_NULL(s);
 
-			pair.val = ch;
-			array::push_back(object, pair);
+		const char* ch = s;
 
-			// 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_null(ch);
+		if ((*ch) == '{')
+		{
+			ch = next(ch, '{');
 
 			ch = skip_whites(ch);
 
@@ -485,13 +447,49 @@ void parse_object(const char* s, Array<JSONPair>& object)
 				return;
 			}
 
-			ch = next(ch, ',');
-			ch = skip_whites(ch);
-		}
-	}
+			while (*ch)
+			{
+				JSONPair pair;
+
+				pair.key = ch;
 
-	CE_FATAL("Bad object");
-}
+				// 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_null(ch);
 
+				ch = skip_whites(ch);
+				ch = next(ch, ':');
+				ch = skip_whites(ch);
+
+				pair.val = ch;
+				array::push_back(object, 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_null(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

+ 23 - 29
engine/core/json/JSON.h

@@ -32,18 +32,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
-template<typename T>
-class List;
-class DynamicString;
-
 /// @defgroup JSON
 
-/// Functions to parse JSON
-///
-/// @ingroup JSON
-namespace json
-{
-
 /// Enumerates JSON value types.
 ///
 /// @ingroup JSON
@@ -69,31 +59,35 @@ struct JSONPair
 	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, DynamicString& str);
+/// Functions to parse JSON-encoded strings.
+///
+/// @ingroup JSON
+namespace json
+{
+	/// Returns the data type of the JSON string @a s. 
+	JSONType::Enum type(const char* s);
 
-/// Returns the value of the @a s JSON number as double.
-double parse_number(const char* s);
+	/// Parses the JSON string @a s ad puts it into @a str.
+	void parse_string(const char* s, DynamicString& str);
 
-/// Returns the value of the @a s JSON boolean.
-bool parse_bool(const char* s);
+	/// Returns the JSON number @a s as double. 
+	double parse_number(const char* s);
 
-/// Returns the value of the @a s JSON number as signed integer.
-int32_t parse_int(const char* s);
+	/// Returns the JSON number @a s as int.
+	int32_t parse_int(const char* s);
 
-/// Returns the value of the @a s JSON number as float.
-float parse_float(const char* s);
+	/// Returns the JSON number @a s 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, Array<const char*>& array);
+	/// Returns the JSON boolean @a s as bool.
+	bool parse_bool(const char* s);
 
-/// 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, Array<JSONPair>& object);
+	/// Parses the JSON array @a s and puts it into @a array as pointers to
+	/// the corresponding items into the original @a s string.
+	void parse_array(const char* s, Array<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, Array<JSONPair>& object);
 } // namespace json
 } // namespace crown

+ 0 - 3
engine/core/json/JSONParser.cpp

@@ -33,9 +33,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
-using json::JSONType;
-using json::JSONPair;
-
 //--------------------------------------------------------------------------
 JSONElement::JSONElement()
 	: m_at(NULL)