diff options
| -rw-r--r-- | src/pugixml.cpp | 142 | ||||
| -rw-r--r-- | src/pugixml.hpp | 8 | ||||
| -rw-r--r-- | src/pugixpath.cpp | 8 | 
3 files changed, 61 insertions, 97 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 346a326..37f52fc 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -2650,6 +2650,41 @@ namespace  			assert(false);
  		}
  	}
 +
 +	template <typename T> xml_parse_result load_stream_impl(xml_document& doc, std::basic_istream<T, std::char_traits<T> >& stream, unsigned int options, encoding_t encoding)
 +	{
 +		if (!stream.good()) return MAKE_PARSE_RESULT(status_io_error);
 +
 +		// get length of remaining data in stream
 +		std::streamoff pos = stream.tellg();
 +		stream.seekg(0, std::ios::end);
 +		std::streamoff length = stream.tellg() - pos;
 +		stream.seekg(pos, std::ios::beg);
 +
 +		if (!stream.good() || pos < 0 || length < 0) return MAKE_PARSE_RESULT(status_io_error);
 +
 +		// read stream data into memory
 +		size_t read_length = static_cast<size_t>(length);
 +
 +		T* s = static_cast<T*>(global_allocate((read_length > 0 ? read_length : 1) * sizeof(T)));
 +		if (!s) return MAKE_PARSE_RESULT(status_out_of_memory);
 +
 +		stream.read(s, static_cast<std::streamsize>(read_length));
 +
 +		// check for errors
 +		size_t actual_length = static_cast<size_t>(stream.gcount());
 +		assert(actual_length <= read_length);
 +
 +		if (read_length > 0 && actual_length == 0)
 +		{
 +			global_deallocate(s);
 +			return MAKE_PARSE_RESULT(status_io_error);
 +		}
 +
 +		// load data from buffer
 +		return doc.load_buffer_inplace_own(s, actual_length * sizeof(T), options, encoding);
 +	}
 +
  }
  namespace pugi
 @@ -3951,54 +3986,14 @@ namespace pugi  	{
  		destroy();
 -		if (!stream.good()) return MAKE_PARSE_RESULT(status_io_error);
 -
 -		std::streamoff length, pos = stream.tellg();
 -		stream.seekg(0, std::ios::end);
 -		length = stream.tellg();
 -		stream.seekg(pos, std::ios::beg);
 -
 -		if (!stream.good()) return MAKE_PARSE_RESULT(status_io_error);
 -
 -		char* s = static_cast<char*>(global_allocate(length > 0 ? length : 1));
 -		if (!s) return MAKE_PARSE_RESULT(status_out_of_memory);
 -
 -		stream.read(s, length);
 -
 -		if (stream.gcount() > length || (length > 0 && stream.gcount() == 0))
 -		{
 -			global_deallocate(s);
 -			return MAKE_PARSE_RESULT(status_io_error);
 -		}
 -
 -		return load_buffer_inplace_own(s, stream.gcount(), options, encoding); // Parse the input string.
 +		return load_stream_impl(*this, stream, options, encoding);
  	}
  	xml_parse_result xml_document::load(std::basic_istream<wchar_t, std::char_traits<wchar_t> >& stream, unsigned int options)
  	{
  		destroy();
 -		if (!stream.good()) return MAKE_PARSE_RESULT(status_io_error);
 -
 -		std::streamoff length, pos = stream.tellg();
 -		stream.seekg(0, std::ios::end);
 -		length = stream.tellg();
 -		stream.seekg(pos, std::ios::beg);
 -
 -		if (!stream.good()) return MAKE_PARSE_RESULT(status_io_error);
 -
 -		wchar_t* s = static_cast<wchar_t*>(global_allocate((length > 0 ? length : 1) * sizeof(wchar_t)));
 -		if (!s) return MAKE_PARSE_RESULT(status_out_of_memory);
 -
 -		stream.read(s, length);
 -
 -		if (stream.gcount() > length || (length > 0 && stream.gcount() == 0))
 -		{
 -			global_deallocate(s);
 -			return MAKE_PARSE_RESULT(status_io_error);
 -		}
 -
 -		return load_buffer_inplace_own(s, stream.gcount() * sizeof(wchar_t), options, encoding_wchar); // Parse the input string.
 +		return load_stream_impl(*this, stream, options, encoding_wchar);
  	}
  #endif
 @@ -4063,7 +4058,7 @@ namespace pugi  		return load_buffer_inplace_own(s, length, options, encoding);
  	}
 -	xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, encoding_t encoding)
 +	xml_parse_result xml_document::load_buffer_impl(void* contents, size_t size, unsigned int options, encoding_t encoding, bool is_mutable, bool own)
  	{
  		destroy();
 @@ -4074,71 +4069,36 @@ namespace pugi  		char_t* buffer;
  		size_t length;
 -		if (!convert_buffer(buffer, length, buffer_encoding, contents, size, false)) return MAKE_PARSE_RESULT(status_out_of_memory);
 +		if (!convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return MAKE_PARSE_RESULT(status_out_of_memory);
 +		// delete original buffer if we performed a conversion
 +		if (own && buffer != contents) global_deallocate(contents);
 +
  		// parse
  		xml_parse_result res = xml_parser::parse(buffer, length, _root, options);
  		// remember encoding
  		res.encoding = buffer_encoding;
 -		// grab onto buffer
 -		_buffer = buffer;
 +		// grab onto buffer if it's our buffer, user is responsible for deallocating contens himself
 +		if (own || buffer != contents) _buffer = buffer;
  		return res;
  	}
 -	xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options, encoding_t encoding)
 +	xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, encoding_t encoding)
  	{
 -		destroy();
 -
 -		// get actual encoding
 -		encoding_t buffer_encoding = get_buffer_encoding(encoding, contents, size);
 -
 -		// get private buffer
 -		char_t* buffer;
 -		size_t length;
 -
 -		if (!convert_buffer(buffer, length, buffer_encoding, contents, size, true)) return MAKE_PARSE_RESULT(status_out_of_memory);
 -		
 -		// parse
 -		xml_parse_result res = 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 (buffer != contents) _buffer = buffer;
 +		return load_buffer_impl(const_cast<void*>(contents), size, options, encoding, false, false);
 +	}
 -		return res;
 +	xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options, encoding_t encoding)
 +	{
 +		return load_buffer_impl(contents, size, options, encoding, true, false);
  	}
  	xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options, encoding_t encoding)
  	{
 -		destroy();
 -
 -		// get actual encoding
 -		encoding_t buffer_encoding = get_buffer_encoding(encoding, contents, size);
 -
 -		// get private buffer
 -		char_t* buffer;
 -		size_t length;
 -
 -		if (!convert_buffer(buffer, length, buffer_encoding, contents, size, true)) return MAKE_PARSE_RESULT(status_out_of_memory);
 -
 -		// delete original buffer if we performed a conversion
 -		if (buffer != contents) global_deallocate(contents);
 -		
 -		// parse
 -		xml_parse_result res = xml_parser::parse(buffer, length, _root, options);
 -
 -		// remember encoding
 -		res.encoding = buffer_encoding;
 -
 -		// grab onto buffer
 -		_buffer = buffer;
 -
 -		return res;
 +		return load_buffer_impl(contents, size, options, encoding, true, true);
  	}
  	void xml_document::save(xml_writer& writer, const char_t* indent, unsigned int flags, encoding_t encoding) const
 diff --git a/src/pugixml.hpp b/src/pugixml.hpp index b9d385f..8b4a733 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -1861,6 +1861,8 @@ namespace pugi  		void create();
  		void destroy();
 +		xml_parse_result load_buffer_impl(void* contents, size_t size, unsigned int options, encoding_t encoding, bool is_mutable, bool own);
 +
  	public:
  		/**
  		 * Default ctor, makes empty document
 @@ -1873,7 +1875,7 @@ namespace pugi  		~xml_document();
  	public:
 -#ifndef PUGIXML_NO_STL
 +	#ifndef PUGIXML_NO_STL
  		/**
  		 * Load document from stream.
  		 *
 @@ -1881,8 +1883,8 @@ namespace pugi  		 * \param options - parsing options
  		 * \return parsing result
  		 */
 -
  		xml_parse_result load(std::basic_istream<char, std::char_traits<char> >& stream, unsigned int options = parse_default, encoding_t encoding = encoding_auto);
 +
  		/**
  		 * Load document from stream.
  		 *
 @@ -1891,7 +1893,7 @@ namespace pugi  		 * \return parsing result
  		 */
  		xml_parse_result load(std::basic_istream<wchar_t, std::char_traits<wchar_t> >& stream, unsigned int options = parse_default);
 -#endif
 +	#endif
  		/**
  		 * Load document from string. String has to be zero-terminated. No encoding conversions are applied.
 diff --git a/src/pugixpath.cpp b/src/pugixpath.cpp index 9d81438..dc25a0e 100644 --- a/src/pugixpath.cpp +++ b/src/pugixpath.cpp @@ -28,15 +28,15 @@  #	include <wchar.h>
  #endif
 -#include <algorithm>
 -#include <string>
 -
  #if defined(_MSC_VER)
  #	pragma warning(disable: 4127) // conditional expression is constant
  #	pragma warning(disable: 4702) // unreachable code
  #	pragma warning(disable: 4996) // this function or variable may be unsafe
  #endif
 +#include <algorithm>
 +#include <string>
 +
  // String utilities prototypes
  namespace pugi
  {
 @@ -787,6 +787,8 @@ namespace pugi  	template <typename Iterator> void xpath_node_set::append(Iterator begin, Iterator end)
  	{
 +		if (begin == end) return;
 +
  		size_t count = std::distance(begin, end);
  		size_t size = m_end - m_begin;
  		size_t capacity = m_eos - m_begin;
  | 
