Browse Source

Read in whole document in xml parser before parsing.

Michael Ragazzon 5 years ago
parent
commit
4531d21618

+ 11 - 10
Include/RmlUi/Core/BaseXMLParser.h

@@ -74,14 +74,22 @@ class RMLUICORE_API BaseXMLParser
 		/// Called when the parser encounters data.
 		virtual void HandleData(const String& data);
 
-	protected:
-		// The stream we're reading the XML from.
-		Stream* xml_source;
+		/// Returns the source URL of this parse. Only valid during parsing.
+		const URL& GetSourceURL() const;
 
 	private:
+		const URL* source_url = nullptr;
+		String xml_source;
+		size_t xml_index = 0;
+
+		void Next();
+		bool AtEnd() const;
+		char Look() const;
+
 		void ReadHeader();
 		void ReadBody();
 
+
 		bool ReadOpenTag();
 		bool ReadCloseTag();
 		bool ReadAttributes(XMLAttributes& attributes);
@@ -99,13 +107,6 @@ class RMLUICORE_API BaseXMLParser
 		// the characters will be consumed.
 		bool PeekString(const char* string, bool consume = true);
 
-		// Fill the buffer as much as possible, without removing any content that is still pending
-		bool FillBuffer();
-
-		unsigned char* read;
-		unsigned char* buffer;
-		int buffer_size;
-		int buffer_used;
 		int line_number;
 		int line_number_open_tag;
 		int open_tag_depth;

+ 0 - 3
Include/RmlUi/Core/XMLParser.h

@@ -64,9 +64,6 @@ public:
 	/// Returns the XML document's header.
 	/// @return The document header.
 	DocumentHeader* GetDocumentHeader();
-	/// Returns the source URL of this parse.
-	/// @return The URL of the parsing stream.
-	const URL& GetSourceURL() const;
 
 	// The parse stack.
 	struct ParseFrame

+ 65 - 96
Source/Core/BaseXMLParser.cpp

@@ -34,15 +34,8 @@
 namespace Rml {
 namespace Core {
 
-// Most file layers cache 4k.
-const int DEFAULT_BUFFER_SIZE = 4096;
-
 BaseXMLParser::BaseXMLParser()
 {
-	read = nullptr;
-	buffer = nullptr;
-	buffer_used = 0;
-	buffer_size = 0;
 	open_tag_depth = 0;
 	treat_content_as_cdata = false;
 }
@@ -62,21 +55,25 @@ void BaseXMLParser::RegisterCDATATag(const String& tag)
 // interesting phenomenon are encountered.
 void BaseXMLParser::Parse(Stream* stream)
 {
-	xml_source = stream;
-	buffer_size = DEFAULT_BUFFER_SIZE;
-	treat_content_as_cdata = false;
+	source_url = &stream->GetSourceURL();
+
+	xml_source.clear();
+	const size_t source_size = stream->Length();
+	const size_t read_size = stream->Read(xml_source, source_size);
+
+	RMLUI_ASSERT(source_size == read_size);
 
-	buffer = (unsigned char*) malloc(buffer_size);
-	read = buffer;
+	xml_index = 0;
 	line_number = 1;
-	FillBuffer();
+	treat_content_as_cdata = false;
 
 	// Read (er ... skip) the header, if one exists.
 	ReadHeader();
 	// Read the XML body.
 	ReadBody();
 
-	free(buffer);
+	xml_source.clear();
+	source_url = nullptr;
 }
 
 // Get the current file line number
@@ -109,11 +106,32 @@ void BaseXMLParser::HandleData(const String& RMLUI_UNUSED_PARAMETER(data))
 	RMLUI_UNUSED(data);
 }
 
+/// Returns the source URL of this parse. Only valid during parsing.
+
+const URL& BaseXMLParser::GetSourceURL() const
+{
+	RMLUI_ASSERT(source_url);
+	return *source_url;
+}
+
 void BaseXMLParser::TreatElementContentAsCDATA()
 {
 	treat_content_as_cdata = true;
 }
 
+void BaseXMLParser::Next() {
+	xml_index += 1;
+}
+
+bool BaseXMLParser::AtEnd() const {
+	return xml_index >= xml_source.size();
+}
+
+char BaseXMLParser::Look() const {
+	RMLUI_ASSERT(!AtEnd());
+	return xml_source[xml_index];
+}
+
 void BaseXMLParser::ReadHeader()
 {
 	if (PeekString("<?"))
@@ -158,10 +176,7 @@ void BaseXMLParser::ReadBody()
 
 			// Bail if we've hit the end of the XML data.
 			if (open_tag_depth == 0)
-			{
-				xml_source->Seek((long)((read - buffer) - buffer_used), SEEK_CUR);
 				break;
-			}
 		}
 		else
 		{
@@ -175,7 +190,7 @@ void BaseXMLParser::ReadBody()
 	// Check for error conditions
 	if (open_tag_depth > 0)
 	{
-		Log::Message(Log::LT_WARNING, "XML parse error on line %d of %s.", GetLineNumber(), xml_source->GetSourceURL().GetURL().c_str());
+		Log::Message(Log::LT_WARNING, "XML parse error on line %d of %s.", GetLineNumber(), source_url->GetURL().c_str());
 	}
 }
 
@@ -399,20 +414,16 @@ bool BaseXMLParser::ReadCDATA(const char* tag_terminator, bool only_terminate_at
 // Reads from the stream until a complete word is found.
 bool BaseXMLParser::FindWord(String& word, const char* terminators)
 {
-	for (;;)
+	while (!AtEnd())
 	{
-		if (read >= buffer + buffer_used)
-		{
-			if (!FillBuffer())			
-				return false;
-		}
+		char c = Look();
 
 		// Ignore white space
-		if (StringUtilities::IsWhitespace(*read))
+		if (StringUtilities::IsWhitespace(c))
 		{
 			if (word.empty())
 			{
-				read++;
+				Next();
 				continue;
 			}
 			else
@@ -420,14 +431,16 @@ bool BaseXMLParser::FindWord(String& word, const char* terminators)
 		}
 
 		// Check for termination condition
-		if (terminators && strchr(terminators, *read))
+		if (terminators && strchr(terminators, c))
 		{
 			return !word.empty();
 		}
 
-		word += *read;
-		read++;
+		word += c;
+		Next();
 	}
+
+	return false;
 }
 
 // Reads from the stream until the given character set is found.
@@ -439,13 +452,10 @@ bool BaseXMLParser::FindString(const char* string, String& data, bool escape_bra
 
 	while (string[index])
 	{
-		if (read >= buffer + buffer_used)
-		{
-			if (!FillBuffer())
-				return false;
-		}
+		if (AtEnd())
+			return false;
 
-		const char c = char(*read);
+		const char c = Look();
 
 		// Count line numbers
 		if (c == '\n')
@@ -477,7 +487,7 @@ bool BaseXMLParser::FindString(const char* string, String& data, bool escape_bra
 		}
 
 		previous = c;
-		read++;
+		Next();
 	}
 
 	return true;
@@ -487,83 +497,42 @@ bool BaseXMLParser::FindString(const char* string, String& data, bool escape_bra
 // given string.
 bool BaseXMLParser::PeekString(const char* string, bool consume)
 {
-	unsigned char* peek_read = read;
-
+	const size_t start_index = xml_index;
+	bool success = true;
 	int i = 0;
 	while (string[i])
 	{
-		// If we're about to read past the end of the buffer, read into the
-		// overflow buffer.
-		if ((peek_read - buffer) + i >= buffer_used)
+		if (AtEnd())
 		{
-			int peek_offset = (int)(peek_read - read);
-			FillBuffer();
-			peek_read = read + peek_offset;
-
-			if (peek_read - buffer + i >= buffer_used)
-			{
-				// Weird, seems our buffer is too small, realloc it bigger.
-				buffer_size *= 2;
-				int read_offset = (int)(read - buffer);
-				unsigned char* new_buffer = (unsigned char*) realloc(buffer, buffer_size);
-				RMLUI_ASSERTMSG(new_buffer != nullptr, "Unable to allocate larger buffer for Peek() call");
-				if(new_buffer == nullptr)
-				{
-					return false;
-				}
-				buffer = new_buffer;
-				// Restore the read pointers.
-				read = buffer + read_offset;
-				peek_read = read + peek_offset;
-				
-				// Attempt to fill our new buffer size.
-				if (!FillBuffer())
-					return false;
-			}
+			success = false;
+			break;
 		}
 
+		const char c = Look();
+
 		// Seek past all the whitespace if we haven't hit the initial character yet.
-		if (i == 0 && StringUtilities::IsWhitespace(*peek_read))
+		if (i == 0 && StringUtilities::IsWhitespace(c))
 		{
-			peek_read++;
+			Next();
 		}
 		else
 		{
-			if (char(*peek_read) != string[i])
-				return false;
+			if (c != string[i])
+			{
+				success = false;
+				break;
+			}
 
 			i++;
-			peek_read++;
+			Next();
 		}
 	}
 
-	// Set the read pointer to the end of the peek.
-	if (consume)
-	{		
-		read = peek_read;
-	}
-
-	return true;
-}
-
-// Fill the buffer as much as possible, without removing any content that is still pending
-bool BaseXMLParser::FillBuffer()
-{
-	int bytes_free = buffer_size;
-	int bytes_remaining = Math::Max((int)(buffer_used - (read - buffer)), 0);
-
-	// If theres any data still in the buffer, shift it down, and fill it again
-	if (bytes_remaining > 0)
-	{
-		memmove(buffer, read, bytes_remaining);
-		bytes_free = buffer_size - bytes_remaining;
-	}
-	
-	read = buffer;
-	size_t bytes_read = xml_source->Read(&buffer[bytes_remaining], bytes_free);
-	buffer_used = (int)(bytes_read + bytes_remaining);
+	// Set the index to the start index unless we are consuming.
+	if (!consume || !success)
+		xml_index = start_index;
 
-	return bytes_read > 0;
+	return success;
 }
 
 }

+ 0 - 5
Source/Core/XMLParser.cpp

@@ -88,11 +88,6 @@ DocumentHeader* XMLParser::GetDocumentHeader()
 	return header.get();
 }
 
-const URL& XMLParser::GetSourceURL() const
-{
-	return xml_source->GetSourceURL();
-}
-
 // Pushes the default element handler onto the parse stack.
 void XMLParser::PushDefaultHandler()
 {