Browse Source

Fix RML parsing of extra hyphen in closing comment

Michael Ragazzon 1 year ago
parent
commit
edcd777ed0
2 changed files with 59 additions and 20 deletions
  1. 6 18
      Source/Core/BaseXMLParser.cpp
  2. 53 2
      Tests/Source/UnitTests/XMLParser.cpp

+ 6 - 18
Source/Core/BaseXMLParser.cpp

@@ -449,16 +449,13 @@ bool BaseXMLParser::FindWord(String& word, const char* terminators)
 
 bool BaseXMLParser::FindString(const char* string, String& data, bool escape_brackets)
 {
-	int index = 0;
+	const char first_char = string[0];
 	bool in_brackets = false;
 	bool in_string = false;
 	char previous = 0;
 
-	while (string[index])
+	while (!AtEnd())
 	{
-		if (AtEnd())
-			return false;
-
 		const char c = Look();
 
 		// Count line numbers
@@ -477,26 +474,17 @@ bool BaseXMLParser::FindString(const char* string, String& data, bool escape_bra
 			}
 		}
 
-		if (c == string[index] && !in_brackets)
-		{
-			index += 1;
-		}
-		else
+		if (c == first_char && !in_brackets && PeekString(string))
 		{
-			if (index > 0)
-			{
-				data += String(string, index);
-				index = 0;
-			}
-
-			data += c;
+			return true;
 		}
 
+		data += c;
 		previous = c;
 		Next();
 	}
 
-	return true;
+	return false;
 }
 
 bool BaseXMLParser::PeekString(const char* string, bool consume)

+ 53 - 2
Tests/Source/UnitTests/XMLParser.cpp

@@ -58,7 +58,7 @@ static const String document_escaping = R"(
 <rml>
     <head>
 	<style>
-	p { 
+	p {
 		font-family: LatoLatin;
 	}
 	</style>
@@ -73,7 +73,7 @@ static const String document_escaping_tags = R"(
 <rml>
     <head>
 	<style>
-	* { 
+	* {
 		font-family: LatoLatin;
 	}
 	</style>
@@ -145,3 +145,54 @@ TEST_CASE("XMLParser.escaping_tags")
 	document->Close();
 	TestsShell::ShutdownShell();
 }
+
+TEST_CASE("XMLParser.comments_and_cdata")
+{
+	const String document_source_pre = R"(
+	<rml>
+	    <head>
+		<style>
+		body {
+			font-family: LatoLatin;
+		}
+		</style>
+	    </head>
+	    <body>)";
+	const String document_source_post = R"(</body></rml>)";
+
+	struct TestCase {
+		String rml;
+		String expected_parsed_rml;
+	};
+
+	const TestCase tests[] = {
+		{"<!-- <xyz> -->", ""},
+		{"<!--<xyz>-->", ""},
+		{"<!-- <xyz> ->-->", ""},
+		{"<!-- <xyz> -- >-->", ""},
+		{"<!-- <xyz> --->", ""},
+		{"<!-- <xyz> ---->", ""},
+		{"<!--- <xyz> ---->", ""},
+		{"<!-- <p> --><p>hello</p><!-- </p> -->", "<p>hello</p>"},
+		{"<![CDATA[hello]]>", "hello"},
+		{"<![CDATA[hello]]]>", "hello]"},
+		{"<![CDATA[hello]]world]]>", "hello]]world"},
+		{"<![CDATA[\"hello\"]]>", "&quot;hello&quot;"},
+		{"<![CDATA[<p>world</p>]]>", "<p>world</p>"},
+	};
+
+	Context* context = TestsShell::GetContext();
+	REQUIRE(context);
+
+	for (const TestCase& test : tests)
+	{
+		ElementDocument* document = context->LoadDocumentFromMemory(document_source_pre + test.rml + document_source_post);
+		REQUIRE(document);
+
+		CHECK(document->GetInnerRML() == test.expected_parsed_rml);
+
+		document->Close();
+		context->Update();
+	}
+	TestsShell::ShutdownShell();
+}