From 09f9ab079e952853fe0f5ed61657f285a2fcd577 Mon Sep 17 00:00:00 2001
From: "arseny.kapoulkine@gmail.com"
 <arseny.kapoulkine@gmail.com@99668b35-9821-0410-8761-19e4c4f06640>
Date: Wed, 31 Oct 2012 04:47:17 +0000
Subject: Adjust parsing so that it is possible to parse a document fragment
 into an existing subtree; can be used to implement append_buffer.

git-svn-id: http://pugixml.googlecode.com/svn/trunk@922 99668b35-9821-0410-8761-19e4c4f06640
---
 src/pugixml.cpp | 89 ++++++++++++++++++++++++++++++---------------------------
 src/pugixml.hpp |  2 --
 2 files changed, 47 insertions(+), 44 deletions(-)

(limited to 'src')

diff --git a/src/pugixml.cpp b/src/pugixml.cpp
index 03a4b9f..168ca0a 100644
--- a/src/pugixml.cpp
+++ b/src/pugixml.cpp
@@ -2380,13 +2380,13 @@ PUGI__NS_BEGIN
 			return s;
 		}
 
-		char_t* parse(char_t* s, xml_node_struct* xmldoc, unsigned int optmsk, char_t endch)
+		char_t* parse(char_t* s, xml_node_struct* root, unsigned int optmsk, char_t endch)
 		{
 			strconv_attribute_t strconv_attribute = get_strconv_attribute(optmsk);
 			strconv_pcdata_t strconv_pcdata = get_strconv_pcdata(optmsk);
 			
 			char_t ch = 0;
-			xml_node_struct* cursor = xmldoc;
+			xml_node_struct* cursor = root;
 			char_t* mark = s;
 
 			while (*s != 0)
@@ -2606,36 +2606,37 @@ PUGI__NS_BEGIN
 			}
 
 			// check that last tag is closed
-			if (cursor != xmldoc) PUGI__THROW_ERROR(status_end_element_mismatch, s);
+			if (cursor != root) PUGI__THROW_ERROR(status_end_element_mismatch, s);
 
 			return s;
 		}
 
-		static xml_parse_result parse(char_t* buffer, size_t length, xml_node_struct* root, unsigned int optmsk)
+		static xml_parse_result parse(char_t* buffer, size_t length, xml_document_struct* xmldoc, xml_node_struct* root, unsigned int optmsk)
 		{
-			xml_document_struct* xmldoc = static_cast<xml_document_struct*>(root);
+			// allocator object is a part of document object
+			xml_allocator& alloc = *static_cast<xml_allocator*>(xmldoc);
 
 			// store buffer for offset_debug
-			xmldoc->buffer = buffer;
+			if (xmldoc == root) xmldoc->buffer = buffer;
 
 			// early-out for empty documents
 			if (length == 0) return make_parse_result(status_ok);
 
 			// create parser on stack
-			xml_parser parser(*xmldoc);
+			xml_parser parser(alloc);
 
 			// save last character and make buffer zero-terminated (speeds up parsing)
 			char_t endch = buffer[length - 1];
 			buffer[length - 1] = 0;
 			
 			// perform actual parsing
-			parser.parse(buffer, xmldoc, optmsk, endch);
+			parser.parse(buffer, root, optmsk, endch);
 
 			xml_parse_result result = make_parse_result(parser.error_status, parser.error_offset ? parser.error_offset - buffer : 0);
 			assert(result.offset >= 0 && static_cast<size_t>(result.offset) <= length);
 
 			// update allocator state
-			*static_cast<xml_allocator*>(xmldoc) = parser.alloc;
+			alloc = parser.alloc;
 
 			// since we removed last character, we have to handle the only possible false positive
 			if (result && endch == '<')
@@ -3650,6 +3651,35 @@ PUGI__NS_BEGIN
 
 		return result == 0;
 	}
+
+	PUGI__FN xml_parse_result load_buffer_impl(xml_document_struct* doc, xml_node_struct* root, void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own, char_t** out_buffer)
+	{
+		// check input buffer
+		assert(contents || size == 0);
+
+		// get actual encoding
+		xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size);
+
+		// get private buffer
+		char_t* buffer = 0;
+		size_t length = 0;
+
+		if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory);
+		
+		// delete original buffer if we performed a conversion
+		if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents);
+
+		// parse
+		xml_parse_result res = impl::xml_parser::parse(buffer, length, doc, root, options);
+
+		// remember encoding
+		res.encoding = buffer_encoding;
+
+		// grab onto buffer if it's our buffer, user is responsible for deallocating contents himself
+		if (own || buffer != contents) *out_buffer = buffer;
+
+		return res;
+	}
 PUGI__NS_END
 
 namespace pugi
@@ -5224,50 +5254,25 @@ namespace pugi
 		return impl::load_file_impl(*this, file, options, encoding);
 	}
 
-	PUGI__FN xml_parse_result xml_document::load_buffer_impl(void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own)
+	PUGI__FN xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding)
 	{
 		reset();
 
-		// check input buffer
-		assert(contents || size == 0);
-
-		// get actual encoding
-		xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size);
-
-		// get private buffer
-		char_t* buffer = 0;
-		size_t length = 0;
-
-		if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory);
-		
-		// delete original buffer if we performed a conversion
-		if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents);
-
-		// parse
-		xml_parse_result res = impl::xml_parser::parse(buffer, length, _root, options);
-
-		// remember encoding
-		res.encoding = buffer_encoding;
-
-		// grab onto buffer if it's our buffer, user is responsible for deallocating contens himself
-		if (own || buffer != contents) _buffer = buffer;
-
-		return res;
-	}
-
-	PUGI__FN xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding)
-	{
-		return load_buffer_impl(const_cast<void*>(contents), size, options, encoding, false, false);
+		return load_buffer_impl(static_cast<impl::xml_document_struct*>(_root), _root, const_cast<void*>(contents), size, options, encoding, false, false, &_buffer);
 	}
 
 	PUGI__FN xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options, xml_encoding encoding)
 	{
-		return load_buffer_impl(contents, size, options, encoding, true, false);
+		reset();
+
+		return load_buffer_impl(static_cast<impl::xml_document_struct*>(_root), _root, contents, size, options, encoding, true, false, &_buffer);
 	}
 		
 	PUGI__FN xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options, xml_encoding encoding)
 	{
-		return load_buffer_impl(contents, size, options, encoding, true, true);
+		reset();
+
+		return load_buffer_impl(static_cast<impl::xml_document_struct*>(_root), _root, contents, size, options, encoding, true, true, &_buffer);
 	}
 
 	PUGI__FN void xml_document::save(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding) const
diff --git a/src/pugixml.hpp b/src/pugixml.hpp
index 898cadc..4ca5197 100644
--- a/src/pugixml.hpp
+++ b/src/pugixml.hpp
@@ -861,8 +861,6 @@ namespace pugi
 		void create();
 		void destroy();
 
-		xml_parse_result load_buffer_impl(void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own);
-
 	public:
 		// Default constructor, makes empty document
 		xml_document();
-- 
cgit v1.2.3