Просмотр исходного кода

core: skip block-closing characters when they appear inside strings

Daniele Bartolini 3 лет назад
Родитель
Сommit
9c7468b54b
4 измененных файлов с 106 добавлено и 11 удалено
  1. 1 0
      docs/changelog.rst
  2. 35 3
      src/core/json/json.cpp
  3. 44 8
      src/core/json/sjson.cpp
  4. 26 0
      src/core/unit_tests.cpp

+ 1 - 0
docs/changelog.rst

@@ -9,6 +9,7 @@ Changelog
 
 * Fixed file changes not detected sometimes.
 * Fixed Ctrl+C/SIGTERM/SIGINT not being honored when launched with --server.
+* Fixed handling of filenames containing some special characters.
 
 **Runtime**
 

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

@@ -50,9 +50,41 @@ namespace json
 		CE_ENSURE(NULL != json);
 
 		switch (*json) {
-		case '"': json = skip_string(json); break;
-		case '[': json = skip_block(json, '[', ']'); break;
-		case '{': json = skip_block(json, '{', '}'); break;
+		case '"':
+			json = skip_string(json);
+			break;
+		case '[':
+		{
+			u32 num = 0;
+
+			for (char ch = *json++; ch != '\0'; ch = *json++) {
+				if (ch == '[') {
+					++num;
+				} else if (ch == ']') {
+					if (--num == 0)
+						break;
+				} else if (ch == '"') {
+					json = skip_string(json);
+				}
+			}
+			break;
+		}
+		case '{':
+		{
+			u32 num = 0;
+
+			for (char ch = *json++; ch != '\0'; ch = *json++) {
+				if (ch == '{') {
+					++num;
+				} else if (ch == '}') {
+					if (--num == 0)
+						break;
+				} else if (ch == '"') {
+					json = skip_string(json);
+				}
+			}
+			break;
+		}
 		default: for (; *json != ',' && *json != '}' && *json != ']'; ++json); break;
 		}
 

+ 44 - 8
src/core/json/sjson.cpp

@@ -53,17 +53,53 @@ namespace sjson
 		case '"':
 			json = skip_string(json);
 			if (*json == '"') {
-				++json;
-				json = strstr(json, "\"\"\"");
+				json = strstr(json + 1, "\"\"\"");
 				CE_ENSURE(json);
-				++json;
-				++json;
-				++json;
+				json += 3;
 			}
 			break;
-
-		case '[': json = skip_block(json, '[', ']'); break;
-		case '{': json = skip_block(json, '{', '}'); break;
+		case '[':
+		{
+			u32 num = 0;
+
+			for (char ch = *json++; ch != '\0'; ch = *json++) {
+				if (ch == '[') {
+					++num;
+				} else if (ch == ']') {
+					if (--num == 0)
+						break;
+				} else if (ch == '"') {
+					json = skip_string(json - 1);
+					if (*json == '"') {
+						json = strstr(json + 1, "\"\"\"");
+						CE_ENSURE(json);
+						json += 3;
+					}
+				}
+			}
+			break;
+		}
+		case '{':
+		{
+			u32 num = 0;
+
+			for (char ch = *json++; ch != '\0'; ch = *json++) {
+				if (ch == '{') {
+					++num;
+				} else if (ch == '}') {
+					if (--num == 0)
+						break;
+				} else if (ch == '"') {
+					json = skip_string(json - 1);
+					if (*json == '"') {
+						json = strstr(json + 1, "\"\"\"");
+						CE_ENSURE(json);
+						json += 3;
+					}
+				}
+			}
+			break;
+		}
 		default: for (; *json != '\0' && *json != ',' && *json != '\n' && *json != ' ' && *json != '}' && *json != ']'; ++json); break;
 		}
 

+ 26 - 0
src/core/unit_tests.cpp

@@ -14,6 +14,7 @@
 #include "core/filesystem/path.h"
 #include "core/guid.inl"
 #include "core/json/json.h"
+#include "core/json/json_object.inl"
 #include "core/json/sjson.h"
 #include "core/math/aabb.inl"
 #include "core/math/color4.inl"
@@ -1165,6 +1166,16 @@ static void test_json()
 		json::parse_string(str, "\"This is JSON\"");
 		ENSURE(strcmp(str.c_str(), "This is JSON") == 0);
 	}
+	{
+		TempAllocator1024 ta;
+		JsonObject obj(ta);
+		json::parse_object(obj, "{\"foo\":{\"}\":false}}");
+	}
+	{
+		TempAllocator1024 ta;
+		JsonObject obj(ta);
+		json::parse_object(obj, "{\"foo\":[\"]\"]}");
+	}
 	memory_globals::shutdown();
 }
 
@@ -1291,6 +1302,21 @@ static void test_sjson()
 		sjson::parse_verbatim(str, "\"\"\"verbatim\"\"\"");
 		ENSURE(strcmp(str.c_str(), "verbatim") == 0);
 	}
+	{
+		TempAllocator1024 ta;
+		JsonObject obj(ta);
+		sjson::parse_object(obj, "{foo={\"}\"=false}}");
+	}
+	{
+		TempAllocator1024 ta;
+		JsonObject obj(ta);
+		sjson::parse_object(obj, "{foo={bar=\"\"\"}\"\"\"}}");
+	}
+	{
+		TempAllocator1024 ta;
+		JsonObject obj(ta);
+		sjson::parse_object(obj, "{foo=[\"]\"]}");
+	}
 	memory_globals::shutdown();
 }