Преглед изворни кода

Refactor JSON to use only pure functions

Daniele Bartolini пре 12 година
родитељ
комит
90ad85b847
2 измењених фајлова са 167 додато и 174 уклоњено
  1. 165 158
      engine/JSON.cpp
  2. 2 16
      engine/JSON.h

+ 165 - 158
engine/JSON.cpp

@@ -28,153 +28,154 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "JSON.h"
 #include "Types.h"
 #include "List.h"
-#include "Allocator.h"
+#include "TempAllocator.h"
 #include <cstdio>
 
 namespace crown
 {
 
-static const char* g_current_char = NULL;
-
 //-----------------------------------------------------------------------------
-char JSON::next(const char* str, const char c, bool force_reset)
+static const char* next(const char* str, const char c = 0)
 {
-	static char* current_str = (char*)str;
-	static size_t index = 0;
-	static char current = str[index];
-
-	if (current_str != str || force_reset == true)
-	{
-		current_str = (char*)str;
-		index = 0;
-		current = str[index];
-	}
+	CE_ASSERT_NOT_NULL(str);
 
-	if (c && c != current)
+	if (c && c != (*str))
 	{
-		CE_ASSERT(false, "Expected '%c' got '%c'", c, current);
+		CE_ASSERT(false, "Expected '%c' got '%c'", c, (*str));
 	}
 
-	index++;
-	current = str[index];
-	g_current_char = &str[index];
-
-	return current;
+	return str + 1;
 }
 
 //-----------------------------------------------------------------------------
-char JSON::skip_whites(const char* s)
+static const char* skip_whites(const char* s)
 {
-	char cur = (*g_current_char);
+	CE_ASSERT_NOT_NULL(s);
 
-	while (cur && cur <= ' ') cur = next(s);
+	const char* ch = s;
 
-	return cur;
+	while ((*ch) && (*ch) <= ' ') ch = next(ch);
+
+	return ch;
 }
 
 //-----------------------------------------------------------------------------
-char JSON::skip_string(const char* s)
+static const char* skip_string(const char* s)
 {
-	char cur = (*g_current_char);
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
 
 	bool escaped = false;
 
-	if (cur == '"')
+	if ((*ch) == '"')
 	{
-		while ((cur = next(s)) != 0)
+		while ((*(ch = next(ch))) != 0)
 		{
-			if (cur == '"' && !escaped)
+			if ((*ch) == '"' && !escaped)
 			{
-				cur = next(s);
-				return cur;
+				ch = next(ch);
+				return ch;
 			}
-			else if (cur == '\\') escaped = true;
+			else if ((*ch) == '\\') escaped = true;
 			else escaped = false;
 		}
 	}
 
-	return cur;
+	return ch;
 }
 
 //-----------------------------------------------------------------------------
-char JSON::skip_number(const char* s)
+static const char* skip_number(const char* s)
 {
-	char cur = (*g_current_char);
+	CE_ASSERT_NOT_NULL(s);
 
-	while (cur && ((cur >= '0' && cur <= '9') || cur == '-' || cur == '.' || cur == '+' ||
-					cur == 'e' || cur == 'E'))  cur = next(s);
+	const char* ch = s;
 
-	return cur;
+	while ((*ch) && (((*ch) >= '0' && (*ch) <= '9') ||
+			(*ch) == '-' || (*ch) == '.' || (*ch) == '+' ||
+			(*ch) == 'e' || (*ch) == 'E'))
+	{
+		ch = next(ch);
+	}
+
+	return ch;
 }
 
 //-----------------------------------------------------------------------------
-char JSON::skip_object(const char* s)
+static const char* skip_object(const char* s)
 {
-	char cur = (*g_current_char);
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
 
 	uint32_t brackets = 1;
 
-	if (cur == '{')
+	if ((*ch) == '{')
 	{
 		brackets++;
-		cur = next(s, '{');
+		ch = next(ch, '{');
 
-		while (cur && brackets != 1)
+		while ((*ch) && brackets != 1)
 		{
-			if (cur == '}') brackets--;
-			else if (cur == '{') brackets++;
-			cur = next(s);
+			if ((*ch) == '}') brackets--;
+			else if ((*ch) == '{') brackets++;
+			ch = next(ch);
 		}
 	}
 
-	return cur;
+	return ch;
 }
 
 //-----------------------------------------------------------------------------
-char JSON::skip_array(const char* s)
+static const char* skip_array(const char* s)
 {
-	char cur = (*g_current_char);
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
 
 	uint32_t brackets = 1;
 
-	if (cur == '[')
+	if ((*ch) == '[')
 	{
 		brackets++;
-		cur = next(s, '[');
+		ch = next(ch, '[');
 
-		while (cur && brackets != 1)
+		while ((*ch) && brackets != 1)
 		{
-			if (cur == ']') brackets--;
-			else if (cur == '[') brackets++;
-			cur = next(s);
+			if ((*ch) == ']') brackets--;
+			else if ((*ch) == '[') brackets++;
+			ch = next(ch);
 		}
 	}
 
-	return cur;
+	return ch;
 }
 
 //-----------------------------------------------------------------------------
-char JSON::skip_bool(const char* s)
+static const char* skip_bool(const char* s)
 {
-	char cur = (*g_current_char);
+	CE_ASSERT_NOT_NULL(s);
+
+	const char* ch = s;
 
-	switch (cur)
+	switch ((*ch))
 	{
 		case 't':
 		{
-			cur = next(s, 't');
-			cur = next(s, 'r');
-			cur = next(s, 'u');
-			cur = next(s, 'e');
+			ch = next(ch, 't');
+			ch = next(ch, 'r');
+			ch = next(ch, 'u');
+			ch = next(ch, 'e');
 			break;
 		}
 		case 'f':
 		{
-			cur = next(s, 'f');
-			cur = next(s, 'a');
-			cur = next(s, 'l');
-			cur = next(s, 's');
-			cur = next(s, 'e');
+			ch = next(ch, 'f');
+			ch = next(ch, 'a');
+			ch = next(ch, 'l');
+			ch = next(ch, 's');
+			ch = next(ch, 'e');
 			break;
 		}
 		default:
@@ -183,11 +184,11 @@ char JSON::skip_bool(const char* s)
 		}
 	}
 
-	return cur;
+	return ch;
 }
 
 //-----------------------------------------------------------------------------
-bool JSON::is_escapee(char c)
+static bool is_escapee(char c)
 {
 	return c == '"' || c == '\\' || c == '/' || c == '\b' || c == '\f' || c == '\n' ||
 			c == '\r' || c == '\t';
@@ -214,39 +215,41 @@ void JSON::parse_string(const char* s, List<char>& str)
 {
 	CE_ASSERT_NOT_NULL(s);
 
-	char cur = '\0';
+	const char* ch = s;
 
-	if (s[0] == '"')
+	if ((*ch) == '"')
 	{
-		while ((cur = next(s)) != 0)
+		while ((*(ch = next(ch))))
 		{
-			if (cur == '"')
+			// Empty string
+			if ((*ch) == '"')
 			{
-				next(s);
+				ch = next(ch);
 				str.push_back('\0');
 				return;
 			}
-			else if (cur == '\\')
+			else if ((*ch) == '\\')
 			{
-				cur = next(s);
+				ch = next(ch);
 
-				if (cur == 'u')
+				if ((*ch) == 'u')
 				{
 					CE_ASSERT(false, "Not supported at the moment");
 				}
-				else if (is_escapee(cur))
+				else if (is_escapee(*ch))
 				{
 					str.push_back('\\');
-					str.push_back(cur);
+					str.push_back(*ch);
 				}
 				else
 				{
-					break; // to invalid string
+					// Go to invalid string
+					break;
 				}
 			}
 			else
 			{
-				str.push_back(cur);
+				str.push_back(*ch);
 			}
 		}
 	}
@@ -259,43 +262,45 @@ double JSON::parse_number(const char* s)
 {
 	CE_ASSERT_NOT_NULL(s);
 
- 	List<char> str(default_allocator());
+	const char* ch = s;
 
- 	char cur = s[0];
+	TempAllocator1024 allocator;
+ 	List<char> str(allocator);
 
-	if (cur == '-')
+	if ((*ch) == '-')
 	{
 		str.push_back('-');
-		cur = next(s, '-');
+		ch = next(ch, '-');
 	}
-	while (cur >= '0' && cur <= '9')
+	while ((*ch) >= '0' && (*ch) <= '9')
 	{
-		str.push_back(cur);
-		cur = next(s);
+		str.push_back((*ch));
+		ch = next(ch);
 	}
 
-	if (cur == '.')
+	if ((*ch) == '.')
 	{
 		str.push_back('.');
-		while ((cur = next(s)) != 0 && cur >= '0' && cur <= '9')
+		while ((*(ch = next(ch))) && (*ch) >= '0' && (*ch) <= '9')
 		{
-			str.push_back(cur);
+			str.push_back(*ch);
 		}
 	}
 
-	if (cur == 'e' || cur == 'E')
+	if ((*ch) == 'e' || (*ch) == 'E')
 	{
-		str.push_back(cur);
-		cur = next(s);
-		if (cur == '-' || cur == '+')
+		str.push_back(*ch);
+		ch = next(ch);
+
+		if ((*ch) == '-' || (*ch) == '+')
 		{
-			str.push_back(cur);
-			cur = next(s);
+			str.push_back(*ch);
+			ch = next(ch);
 		}
-		while (cur >= '0' && cur <= '9')
+		while ((*ch) >= '0' && (*ch) <= '9')
 		{
-			str.push_back(cur);
-			cur = next(s);
+			str.push_back(*ch);
+			ch = next(ch);
 		}
 	}
 
@@ -315,23 +320,25 @@ bool JSON::parse_bool(const char* s)
 {
 	CE_ASSERT_NOT_NULL(s);
 
-	switch(s[0])
+	const char* ch = s;
+
+	switch(*ch)
 	{
 		case 't':
 		{
-			next(s, 't');
-			next(s, 'r');
-			next(s, 'u');
-			next(s, 'e');
+			ch = next(ch, 't');
+			ch = next(ch, 'r');
+			ch = next(ch, 'u');
+			ch = next(ch, 'e');
 			return true;
 		}
 		case 'f':
 		{
-			next(s, 'f');
-			next(s, 'a');
-			next(s, 'l');
-			next(s, 's');			
-			next(s, 'e');
+			ch = next(ch, 'f');
+			ch = next(ch, 'a');
+			ch = next(ch, 'l');
+			ch = next(ch, 's');			
+			ch = next(ch, 'e');
 			return false;
 		}
 		default: break;
@@ -361,48 +368,48 @@ void JSON::parse_array(const char* s, List<const char*>& array)
 {
 	CE_ASSERT_NOT_NULL(s);
 
-	char cur = s[0];
+	const char* ch = s;
 
-	if (cur == '[')
+	if ((*ch) == '[')
 	{
-		cur = next(s, '[');
+		ch = next(ch, '[');
 
 		// Skip whitespaces
-		while (cur && cur <= ' ')
+		while ((*ch) && (*ch) <= ' ')
 		{
-			cur = next(s);
+			ch = next(ch);
 		}
 
-		if (cur == ']')
+		if ((*ch) == ']')
 		{
-			cur = next(s, ']');
+			ch = next(ch, ']');
 			return;
 		}
 
-		while (cur)
+		while (*ch)
 		{
-			array.push_back(g_current_char);
+			array.push_back(ch);
 
-			cur = skip_array(s);
-			cur = skip_object(s);
-			cur = skip_number(s);
-			cur = skip_string(s);
-			cur = skip_bool(s);
+			ch = skip_array(ch);
+			ch = skip_object(ch);
+			ch = skip_number(ch);
+			ch = skip_string(ch);
+			ch = skip_bool(ch);
 
-			cur = skip_whites(s);
+			ch = skip_whites(ch);
 
 			// Closing bracket (top-most array)
-			if (cur == ']')
+			if ((*ch) == ']')
 			{
-				cur = next(s, ']');
+				ch = next(ch, ']');
 				return;
 			}
 
 			// Skip until next ','
-			cur = next(s, ',');
+			ch = next(ch, ',');
 
 			// Skip whites, eventually
-			cur = skip_whites(s);
+			ch = skip_whites(ch);
 		}
 	}
 
@@ -414,57 +421,57 @@ void JSON::parse_object(const char* s, List<JSONPair>& map)
 {
 	CE_ASSERT_NOT_NULL(s);
 
-	char cur = s[0];
+	const char* ch = s;
 
-	if (cur == '{')
+	if ((*ch) == '{')
 	{
-		cur = next(s, '{');
+		ch = next(ch, '{');
 
-		cur = skip_whites(s);
+		ch = skip_whites(ch);
 
-		if (cur == '}')
+		if ((*ch) == '}')
 		{
-			next(s, '}');
+			next(ch, '}');
 			return;
 		}
 
-		while (cur)
+		while (*ch)
 		{
 			JSONPair pair;
 
-			pair.key = g_current_char;
+			pair.key = ch;
 
 			// Skip any value
-			cur = skip_array(s);
-			cur = skip_object(s);
-			cur = skip_number(s);
-			cur = skip_string(s);
-			cur = skip_bool(s);
+			ch = skip_array(ch);
+			ch = skip_object(ch);
+			ch = skip_number(ch);
+			ch = skip_string(ch);
+			ch = skip_bool(ch);
 
-			cur = skip_whites(s);
-			cur = next(s, ':');
-			cur = skip_whites(s);
+			ch = skip_whites(ch);
+			ch = next(ch, ':');
+			ch = skip_whites(ch);
 
-			pair.val = g_current_char;
+			pair.val = ch;
 			map.push_back(pair);
 
 			// Skip any value
-			cur = skip_array(s);
-			cur = skip_object(s);
-			cur = skip_number(s);
-			cur = skip_string(s);
-			cur = skip_bool(s);
+			ch = skip_array(ch);
+			ch = skip_object(ch);
+			ch = skip_number(ch);
+			ch = skip_string(ch);
+			ch = skip_bool(ch);
 
-			cur = skip_whites(s);
+			ch = skip_whites(ch);
 
-			if (cur == '}')
+			if ((*ch) == '}')
 			{
-				next(s, '}');
+				next(ch, '}');
 				return;
 			}
 
-			cur = next(s, ',');
-			cur = skip_whites(s);
+			ch = next(ch, ',');
+			ch = skip_whites(ch);
 		}
 	}
 

+ 2 - 16
engine/JSON.h

@@ -28,7 +28,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "Types.h"
 #include "List.h"
-#include "Map.h"
 
 namespace crown
 {
@@ -53,10 +52,6 @@ class JSON
 {
 public:
 
-	static char			next(const char* s, const char c = 0, bool force_reset = false);
-
-	static bool			is_escapee(char c);
-
 	static JSONType		type(const char* s);
 
 	static void			parse_string(const char* s, List<char>& str);
@@ -67,16 +62,7 @@ public:
 	static float		parse_float(const char* s);
 
 	static void			parse_array(const char* s, List<const char*>& array);
-	static void			parse_object(const char* s, List<JSONPair> & map);
-
-private:
-
-	static char			skip_whites(const char* s);
-	static char 		skip_string(const char* s);
-	static char 		skip_number(const char* s);
-	static char 		skip_object(const char* s);
-	static char			skip_array(const char* s);
-	static char			skip_bool(const char* s);
+	static void			parse_object(const char* s, List<JSONPair>& map);
 };
 
-} // namespace crown
+} // namespace crown