diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/pugiconfig.hpp | 3 | ||||
| -rw-r--r-- | src/pugixml.cpp | 314 | ||||
| -rw-r--r-- | src/pugixml.hpp | 22 | 
3 files changed, 222 insertions, 117 deletions
diff --git a/src/pugiconfig.hpp b/src/pugiconfig.hpp index 56f1d22..6219dbe 100644 --- a/src/pugiconfig.hpp +++ b/src/pugiconfig.hpp @@ -1,5 +1,5 @@  /** - * pugixml parser - version 1.4 + * pugixml parser - version 1.5   * --------------------------------------------------------   * Copyright (C) 2006-2014, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)   * Report bugs and download new versions at http://pugixml.org/ @@ -39,7 +39,6 @@  // Uncomment this to switch to header-only version  // #define PUGIXML_HEADER_ONLY -// #include "pugixml.cpp"  // Uncomment this to enable long long support  // #define PUGIXML_HAS_LONG_LONG diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 1d390eb..787f693 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -1,6 +1,5 @@  /** -{ - * pugixml parser - version 1.4 + * pugixml parser - version 1.5   * --------------------------------------------------------   * Copyright (C) 2006-2014, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)   * Report bugs and download new versions at http://pugixml.org/ @@ -286,8 +285,6 @@ PUGI__NS_BEGIN  	{  		static xml_memory_page* construct(void* memory)  		{ -			if (!memory) return 0; //$ redundant, left for performance -  			xml_memory_page* result = static_cast<xml_memory_page*>(memory);  			result->allocator = 0; @@ -328,7 +325,7 @@ PUGI__NS_BEGIN  			void* memory = xml_memory::allocate(size + xml_memory_page_alignment);  			if (!memory) return 0; -			// align upwards to page boundary (note: this guarantees at least 1 usable byte before the page) +			// align to next page boundary (note: this guarantees at least 1 usable byte before the page)  			char* page_memory = reinterpret_cast<char*>((reinterpret_cast<uintptr_t>(memory) + xml_memory_page_alignment) & ~(xml_memory_page_alignment - 1));  			// prepare page structure @@ -338,6 +335,7 @@ PUGI__NS_BEGIN  			page->allocator = _root->allocator;  			// record the offset for freeing the memory block +			assert(page_memory > memory && page_memory - static_cast<char*>(memory) <= 127);  			page_memory[-1] = static_cast<char>(page_memory - static_cast<char*>(memory));  			return page; @@ -402,6 +400,8 @@ PUGI__NS_BEGIN  		char_t* allocate_string(size_t length)  		{ +			PUGI__STATIC_ASSERT(xml_memory_page_size <= (1 << 16)); +  			// allocate memory for string and header block  			size_t size = sizeof(xml_memory_string_header) + length * sizeof(char_t); @@ -711,6 +711,7 @@ PUGI__NS_BEGIN  		else  			parent->first_child = node->next_sibling; +		node->parent = 0;  		node->prev_sibling_c = 0;  		node->next_sibling = 0;  	} @@ -2356,23 +2357,28 @@ PUGI__NS_BEGIN  		char_t* parse_doctype_ignore(char_t* s)  		{ +			size_t depth = 0; +  			assert(s[0] == '<' && s[1] == '!' && s[2] == '['); -			s++; +			s += 3;  			while (*s)  			{  				if (s[0] == '<' && s[1] == '!' && s[2] == '[')  				{  					// nested ignore section -					s = parse_doctype_ignore(s); -					if (!s) return s; +					s += 3; +					depth++;  				}  				else if (s[0] == ']' && s[1] == ']' && s[2] == '>')  				{  					// ignore section end  					s += 3; -					return s; +					if (depth == 0) +						return s; + +					depth--;  				}  				else s++;  			} @@ -2380,10 +2386,12 @@ PUGI__NS_BEGIN  			PUGI__THROW_ERROR(status_bad_doctype, s);  		} -		char_t* parse_doctype_group(char_t* s, char_t endch, bool toplevel) +		char_t* parse_doctype_group(char_t* s, char_t endch)  		{ +			size_t depth = 0; +  			assert((s[0] == '<' || s[0] == 0) && s[1] == '!'); -			s++; +			s += 2;  			while (*s)  			{ @@ -2398,12 +2406,8 @@ PUGI__NS_BEGIN  					else  					{  						// some control group -						s = parse_doctype_group(s, endch, false); -						if (!s) return s; - -						// skip > -						assert(*s == '>'); -						s++; +						s += 2; +						depth++;  					}  				}  				else if (s[0] == '<' || s[0] == '"' || s[0] == '\'') @@ -2414,12 +2418,16 @@ PUGI__NS_BEGIN  				}  				else if (*s == '>')  				{ -					return s; +					if (depth == 0) +						return s; + +					depth--; +					s++;  				}  				else s++;  			} -			if (!toplevel || endch != '>') PUGI__THROW_ERROR(status_bad_doctype, s); +			if (depth != 0 || endch != '>') PUGI__THROW_ERROR(status_bad_doctype, s);  			return s;  		} @@ -2511,7 +2519,7 @@ PUGI__NS_BEGIN  				char_t* mark = s + 9; -				s = parse_doctype_group(s, endch, true); +				s = parse_doctype_group(s, endch);  				if (!s) return s;  				assert((*s == 0 && endch == '>') || *s == '>'); @@ -2670,15 +2678,11 @@ PUGI__NS_BEGIN  									a->name = s; // Save the offset.  									PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. -									PUGI__CHECK_ERROR(status_bad_attribute, s); //$ redundant, left for performance -  									PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. -									PUGI__CHECK_ERROR(status_bad_attribute, s); //$ redundant, left for performance  									if (PUGI__IS_CHARTYPE(ch, ct_space))  									{  										PUGI__SKIPWS(); // Eat any whitespace. -										PUGI__CHECK_ERROR(status_bad_attribute, s); //$ redundant, left for performance  										ch = *s;  										++s; @@ -3647,11 +3651,12 @@ PUGI__NS_BEGIN  				}  				node = node->parent; -				depth--;  				// write closing node  				if (PUGI__NODETYPE(node) == node_element)  				{ +					depth--; +  					if (indent_length)  						text_output_indent(writer, indent, indent_length, depth); @@ -3662,11 +3667,11 @@ PUGI__NS_BEGIN  		while (node != root);  	} -	PUGI__FN bool has_declaration(xml_node node) +	PUGI__FN bool has_declaration(xml_node_struct* node)  	{ -		for (xml_node child = node.first_child(); child; child = child.next_sibling()) +		for (xml_node_struct* child = node->first_child; child; child = child->next_sibling)  		{ -			xml_node_type type = child.type(); +			xml_node_type type = PUGI__NODETYPE(child);  			if (type == node_declaration) return true;  			if (type == node_element) return false; @@ -3684,6 +3689,11 @@ PUGI__NS_BEGIN  		return false;  	} +	PUGI__FN bool allow_insert_attribute(xml_node_type parent) +	{ +		return parent == node_element || parent == node_declaration; +	} +  	PUGI__FN bool allow_insert_child(xml_node_type parent, xml_node_type child)  	{  		if (parent != node_document && parent != node_element) return false; @@ -3719,6 +3729,8 @@ PUGI__NS_BEGIN  	PUGI__FN void node_copy_string(char_t*& dest, uintptr_t& header, uintptr_t header_mask, char_t* source, uintptr_t& source_header, xml_allocator* alloc)  	{ +		assert(!dest && (header & header_mask) == 0); +  		if (source)  		{  			if (alloc && (source_header & header_mask) == 0) @@ -3949,10 +3961,18 @@ PUGI__NS_BEGIN  		return set_value_buffer(dest, header, header_mask, buf);  	} +	PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, float value) +	{ +		char buf[128]; +		sprintf(buf, "%.9g", value); + +		return set_value_buffer(dest, header, header_mask, buf); +	} +	  	PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, double value)  	{  		char buf[128]; -		sprintf(buf, "%g", value); +		sprintf(buf, "%.17g", value);  		return set_value_buffer(dest, header, header_mask, buf);  	} @@ -3990,7 +4010,7 @@ PUGI__NS_BEGIN  		_fseeki64(file, 0, SEEK_END);  		length_type length = _ftelli64(file);  		_fseeki64(file, 0, SEEK_SET); -	#elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && !defined(__STRICT_ANSI__) +	#elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))  		// there are 64-bit versions of fseek/ftell, let's use them  		typedef off64_t length_type; @@ -4235,7 +4255,7 @@ PUGI__NS_BEGIN  	}  #endif -#if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && !defined(__STRICT_ANSI__)) +#if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR)))  	PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode)  	{  		return _wfopen(path, mode); @@ -4545,6 +4565,12 @@ namespace pugi  		return *this;  	} +	PUGI__FN xml_attribute& xml_attribute::operator=(float rhs) +	{ +		set_value(rhs); +		return *this; +	} +	  	PUGI__FN xml_attribute& xml_attribute::operator=(bool rhs)  	{  		set_value(rhs); @@ -4600,6 +4626,13 @@ namespace pugi  		return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);  	} +	PUGI__FN bool xml_attribute::set_value(float rhs) +	{ +		if (!_attr) return false; + +		return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); +	} +	  	PUGI__FN bool xml_attribute::set_value(bool rhs)  	{  		if (!_attr) return false; @@ -4803,11 +4836,7 @@ namespace pugi  	PUGI__FN xml_node xml_node::root() const  	{ -		if (!_root) return xml_node(); - -		impl::xml_memory_page* page = reinterpret_cast<impl::xml_memory_page*>(_root->header & impl::xml_memory_page_pointer_mask); - -		return xml_node(static_cast<impl::xml_document_struct*>(page->allocator)); +		return _root ? xml_node(&impl::get_document(_root)) : xml_node();  	}  	PUGI__FN xml_text xml_node::text() const @@ -4883,7 +4912,7 @@ namespace pugi  	PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_)  	{ -		if (type() != node_element && type() != node_declaration) return xml_attribute(); +		if (!impl::allow_insert_attribute(type())) return xml_attribute();  		xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root)));  		if (!a) return xml_attribute(); @@ -4897,7 +4926,7 @@ namespace pugi  	PUGI__FN xml_attribute xml_node::prepend_attribute(const char_t* name_)  	{ -		if (type() != node_element && type() != node_declaration) return xml_attribute(); +		if (!impl::allow_insert_attribute(type())) return xml_attribute();  		xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root)));  		if (!a) return xml_attribute(); @@ -4911,7 +4940,7 @@ namespace pugi  	PUGI__FN xml_attribute xml_node::insert_attribute_after(const char_t* name_, const xml_attribute& attr)  	{ -		if (type() != node_element && type() != node_declaration) return xml_attribute(); +		if (!impl::allow_insert_attribute(type())) return xml_attribute();  		if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();  		xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); @@ -4926,7 +4955,7 @@ namespace pugi  	PUGI__FN xml_attribute xml_node::insert_attribute_before(const char_t* name_, const xml_attribute& attr)  	{ -		if (type() != node_element && type() != node_declaration) return xml_attribute(); +		if (!impl::allow_insert_attribute(type())) return xml_attribute();  		if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();  		xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); @@ -4981,7 +5010,7 @@ namespace pugi  	PUGI__FN xml_node xml_node::append_child(xml_node_type type_)  	{ -		if (!impl::allow_insert_child(this->type(), type_)) return xml_node(); +		if (!impl::allow_insert_child(type(), type_)) return xml_node();  		xml_node n(impl::allocate_node(impl::get_allocator(_root), type_));  		if (!n) return xml_node(); @@ -4995,7 +5024,7 @@ namespace pugi  	PUGI__FN xml_node xml_node::prepend_child(xml_node_type type_)  	{ -		if (!impl::allow_insert_child(this->type(), type_)) return xml_node(); +		if (!impl::allow_insert_child(type(), type_)) return xml_node();  		xml_node n(impl::allocate_node(impl::get_allocator(_root), type_));  		if (!n) return xml_node(); @@ -5009,7 +5038,7 @@ namespace pugi  	PUGI__FN xml_node xml_node::insert_child_before(xml_node_type type_, const xml_node& node)  	{ -		if (!impl::allow_insert_child(this->type(), type_)) return xml_node(); +		if (!impl::allow_insert_child(type(), type_)) return xml_node();  		if (!node._root || node._root->parent != _root) return xml_node();  		xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); @@ -5024,7 +5053,7 @@ namespace pugi  	PUGI__FN xml_node xml_node::insert_child_after(xml_node_type type_, const xml_node& node)  	{ -		if (!impl::allow_insert_child(this->type(), type_)) return xml_node(); +		if (!impl::allow_insert_child(type(), type_)) return xml_node();  		if (!node._root || node._root->parent != _root) return xml_node();  		xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); @@ -5075,38 +5104,60 @@ namespace pugi  	PUGI__FN xml_node xml_node::append_copy(const xml_node& proto)  	{ -		xml_node result = append_child(proto.type()); +		xml_node_type type_ = proto.type(); +		if (!impl::allow_insert_child(type(), type_)) return xml_node(); -		if (result) impl::node_copy_tree(result.internal_object(), proto.internal_object()); +		xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); +		if (!n) return xml_node(); -		return result; +		impl::append_node(n._root, _root); +		impl::node_copy_tree(n._root, proto._root); + +		return n;  	}  	PUGI__FN xml_node xml_node::prepend_copy(const xml_node& proto)  	{ -		xml_node result = prepend_child(proto.type()); +		xml_node_type type_ = proto.type(); +		if (!impl::allow_insert_child(type(), type_)) return xml_node(); -		if (result) impl::node_copy_tree(result.internal_object(), proto.internal_object()); +		xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); +		if (!n) return xml_node(); -		return result; +		impl::prepend_node(n._root, _root); +		impl::node_copy_tree(n._root, proto._root); + +		return n;  	}  	PUGI__FN xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node)  	{ -		xml_node result = insert_child_after(proto.type(), node); +		xml_node_type type_ = proto.type(); +		if (!impl::allow_insert_child(type(), type_)) return xml_node(); +		if (!node._root || node._root->parent != _root) return xml_node(); -		if (result) impl::node_copy_tree(result.internal_object(), proto.internal_object()); +		xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); +		if (!n) return xml_node(); -		return result; +		impl::insert_node_after(n._root, node._root); +		impl::node_copy_tree(n._root, proto._root); + +		return n;  	}  	PUGI__FN xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node)  	{ -		xml_node result = insert_child_before(proto.type(), node); +		xml_node_type type_ = proto.type(); +		if (!impl::allow_insert_child(type(), type_)) return xml_node(); +		if (!node._root || node._root->parent != _root) return xml_node(); -		if (result) impl::node_copy_tree(result.internal_object(), proto.internal_object()); +		xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); +		if (!n) return xml_node(); -		return result; +		impl::insert_node_before(n._root, node._root); +		impl::node_copy_tree(n._root, proto._root); + +		return n;  	}  	PUGI__FN xml_node xml_node::append_move(const xml_node& moved) @@ -5202,8 +5253,7 @@ namespace pugi  		if (!impl::allow_insert_child(type(), node_element)) return impl::make_parse_result(status_append_invalid_root);  		// get document node -		impl::xml_document_struct* doc = static_cast<impl::xml_document_struct*>(root()._root); -		assert(doc); +		impl::xml_document_struct* doc = &impl::get_document(_root);  		// disable document_buffer_order optimization since in a document with multiple buffers comparing buffer pointers does not make sense  		doc->header |= impl::xml_memory_page_contents_shared_mask; @@ -5414,13 +5464,12 @@ namespace pugi  	PUGI__FN ptrdiff_t xml_node::offset_debug() const  	{ -		xml_node_struct* r = root()._root; +		if (!_root) return -1; -		if (!r) return -1; +		impl::xml_document_struct& doc = impl::get_document(_root); -		const char_t* buffer = static_cast<impl::xml_document_struct*>(r)->buffer; - -		if (!buffer) return -1; +		// we can determine the offset reliably only if there is exactly once parse buffer +		if (!doc.buffer || doc.extra_buffers) return -1;  		switch (type())  		{ @@ -5430,13 +5479,13 @@ namespace pugi  		case node_element:  		case node_declaration:  		case node_pi: -			return (_root->header & impl::xml_memory_page_name_allocated_or_shared_mask) ? -1 : _root->name - buffer; +			return _root->name && (_root->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0 ? _root->name - doc.buffer : -1;  		case node_pcdata:  		case node_cdata:  		case node_comment:  		case node_doctype: -			return (_root->header & impl::xml_memory_page_value_allocated_or_shared_mask) ? -1 : _root->value - buffer; +			return _root->value && (_root->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0 ? _root->value - doc.buffer : -1;  		default:  			return -1; @@ -5587,6 +5636,13 @@ namespace pugi  		return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false;  	} +	PUGI__FN bool xml_text::set(float rhs) +	{ +		xml_node_struct* dn = _data_new(); + +		return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; +	} +  	PUGI__FN bool xml_text::set(double rhs)  	{  		xml_node_struct* dn = _data_new(); @@ -5641,6 +5697,12 @@ namespace pugi  		return *this;  	} +	PUGI__FN xml_text& xml_text::operator=(float rhs) +	{ +		set(rhs); +		return *this; +	} +  	PUGI__FN xml_text& xml_text::operator=(bool rhs)  	{  		set(rhs); @@ -5981,6 +6043,7 @@ namespace pugi  		// destroy dynamic storage, leave sentinel page (it's in static memory)  		impl::xml_memory_page* root_page = reinterpret_cast<impl::xml_memory_page*>(_root->header & impl::xml_memory_page_pointer_mask);  		assert(root_page && !root_page->prev); +		assert(reinterpret_cast<char*>(root_page) >= _memory && reinterpret_cast<char*>(root_page) < _memory + sizeof(_memory));  		for (impl::xml_memory_page* page = root_page->next; page; )  		{ @@ -6010,7 +6073,7 @@ namespace pugi  	}  #endif -	PUGI__FN xml_parse_result xml_document::load(const char_t* contents, unsigned int options) +	PUGI__FN xml_parse_result xml_document::load_string(const char_t* contents, unsigned int options)  	{  		// Force native encoding (skip autodetection)  	#ifdef PUGIXML_WCHAR_MODE @@ -6022,6 +6085,11 @@ namespace pugi  		return load_buffer(contents, impl::strlength(contents) * sizeof(char_t), options, encoding);  	} +	PUGI__FN xml_parse_result xml_document::load(const char_t* contents, unsigned int options) +	{ +		return load_string(contents, options); +	} +  	PUGI__FN xml_parse_result xml_document::load_file(const char* path_, unsigned int options, xml_encoding encoding)  	{  		reset(); @@ -6076,7 +6144,7 @@ namespace pugi  		#endif  		} -		if (!(flags & format_no_declaration) && !impl::has_declaration(*this)) +		if (!(flags & format_no_declaration) && !impl::has_declaration(_root))  		{  			buffered_writer.write_string(PUGIXML_TEXT("<?xml version=\"1.0\""));  			if (encoding == encoding_latin1) buffered_writer.write_string(PUGIXML_TEXT(" encoding=\"ISO-8859-1\"")); @@ -7384,7 +7452,7 @@ PUGI__NS_BEGIN  		return node.attribute() ? namespace_uri(node.attribute(), node.parent()) : namespace_uri(node.node());  	} -	PUGI__FN void normalize_space(char_t* buffer) +	PUGI__FN char_t* normalize_space(char_t* buffer)  	{  		char_t* write = buffer; @@ -7408,9 +7476,11 @@ PUGI__NS_BEGIN  		// zero-terminate  		*write = 0; + +		return write;  	} -	PUGI__FN void translate(char_t* buffer, const char_t* from, const char_t* to, size_t to_length) +	PUGI__FN char_t* translate(char_t* buffer, const char_t* from, const char_t* to, size_t to_length)  	{  		char_t* write = buffer; @@ -7428,6 +7498,8 @@ PUGI__NS_BEGIN  		// zero-terminate  		*write = 0; + +		return write;  	}  	PUGI__FN unsigned char* translate_table_generate(xpath_allocator* alloc, const char_t* from, const char_t* to) @@ -7442,6 +7514,7 @@ PUGI__NS_BEGIN  			if (fc >= 128 || tc >= 128)  				return 0; +			// code=128 means "skip character"  			if (!table[fc])  				table[fc] = static_cast<unsigned char>(tc ? tc : 128); @@ -7463,7 +7536,7 @@ PUGI__NS_BEGIN  		return static_cast<unsigned char*>(result);  	} -	PUGI__FN void translate_table(char_t* buffer, const unsigned char* table) +	PUGI__FN char_t* translate_table(char_t* buffer, const unsigned char* table)  	{  		char_t* write = buffer; @@ -7476,6 +7549,8 @@ PUGI__NS_BEGIN  			{  				unsigned char code = table[index]; +				// code=128 means "skip character" (table size is 128 so 128 can be a special value) +				// this code skips these characters without extra branches  				*write = static_cast<char_t>(code);  				write += 1 - (code >> 7);  			} @@ -7487,6 +7562,8 @@ PUGI__NS_BEGIN  		// zero-terminate  		*write = 0; + +		return write;  	}  	inline bool is_xpath_attribute(const char_t* name) @@ -7749,26 +7826,14 @@ PUGI__NS_BEGIN  			return xpath_first(_begin, _end, _type);  		} +		void push_back_grow(const xpath_node& node, xpath_allocator* alloc); +  		void push_back(const xpath_node& node, xpath_allocator* alloc)  		{ -			if (_end == _eos) -			{ -				size_t capacity = static_cast<size_t>(_eos - _begin); - -				// get new capacity (1.5x rule) -				size_t new_capacity = capacity + capacity / 2 + 1; - -				// reallocate the old array or allocate a new one -				xpath_node* data = static_cast<xpath_node*>(alloc->reallocate(_begin, capacity * sizeof(xpath_node), new_capacity * sizeof(xpath_node))); -				assert(data); - -				// finalize -				_begin = data; -				_end = data + capacity; -				_eos = data + new_capacity; -			} - -			*_end++ = node; +			if (_end != _eos) +				*_end++ = node; +			else +				push_back_grow(node, alloc);  		}  		void append(const xpath_node* begin_, const xpath_node* end_, xpath_allocator* alloc) @@ -7825,6 +7890,26 @@ PUGI__NS_BEGIN  			_type = value;  		}  	}; + +	PUGI__FN_NO_INLINE void xpath_node_set_raw::push_back_grow(const xpath_node& node, xpath_allocator* alloc) +	{ +		size_t capacity = static_cast<size_t>(_eos - _begin); + +		// get new capacity (1.5x rule) +		size_t new_capacity = capacity + capacity / 2 + 1; + +		// reallocate the old array or allocate a new one +		xpath_node* data = static_cast<xpath_node*>(alloc->reallocate(_begin, capacity * sizeof(xpath_node), new_capacity * sizeof(xpath_node))); +		assert(data); + +		// finalize +		_begin = data; +		_end = data + capacity; +		_eos = data + new_capacity; + +		// push +		*_end++ = node; +	}  PUGI__NS_END  PUGI__NS_BEGIN @@ -8432,9 +8517,9 @@ PUGI__NS_BEGIN  			return false;  		} -		static bool eval_once(bool forward, nodeset_eval_t eval) +		static bool eval_once(xpath_node_set::type_t type, nodeset_eval_t eval)  		{ -			return forward ? eval != nodeset_eval_all : eval == nodeset_eval_any; +			return type == xpath_node_set::type_sorted ? eval != nodeset_eval_all : eval == nodeset_eval_any;  		}  		template <class Comp> static bool compare_rel(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp) @@ -8606,7 +8691,7 @@ PUGI__NS_BEGIN  		{  			if (ns.size() == first) return; -			bool last_once = eval_once(ns.type() == xpath_node_set::type_sorted, eval); +			bool last_once = eval_once(ns.type(), eval);  			for (xpath_ast_node* pred = _right; pred; pred = pred->_next)  				pred->apply_predicate(ns, first, stack, !pred->_next && last_once); @@ -8614,7 +8699,7 @@ PUGI__NS_BEGIN  		bool step_push(xpath_node_set_raw& ns, xml_attribute_struct* a, xml_node_struct* parent, xpath_allocator* alloc)  		{ -            assert(a); +			assert(a);  			const char_t* name = a->name ? a->name : PUGIXML_TEXT(""); @@ -8654,7 +8739,7 @@ PUGI__NS_BEGIN  		bool step_push(xpath_node_set_raw& ns, xml_node_struct* n, xpath_allocator* alloc)  		{ -            assert(n); +			assert(n);  			xml_node_type type = PUGI__NODETYPE(n); @@ -9004,7 +9089,7 @@ PUGI__NS_BEGIN  		template <class T> void step_fill(xpath_node_set_raw& ns, const xpath_node& xn, xpath_allocator* alloc, bool once, T v)  		{  			const axis_t axis = T::axis; -			bool axis_has_attributes = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_descendant_or_self || axis == axis_following || axis == axis_parent || axis == axis_preceding || axis == axis_self); +			const bool axis_has_attributes = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_descendant_or_self || axis == axis_following || axis == axis_parent || axis == axis_preceding || axis == axis_self);  			if (xn.node())  				step_fill(ns, xn.node().internal_object(), alloc, once, v); @@ -9015,15 +9100,16 @@ PUGI__NS_BEGIN  		template <class T> xpath_node_set_raw step_do(const xpath_context& c, const xpath_stack& stack, nodeset_eval_t eval, T v)  		{  			const axis_t axis = T::axis; -			bool axis_reverse = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_preceding || axis == axis_preceding_sibling); +			const bool axis_reverse = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_preceding || axis == axis_preceding_sibling); +			const xpath_node_set::type_t axis_type = axis_reverse ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted;  			bool once =  				(axis == axis_attribute && _test == nodetest_name) || -				(!_right && eval_once(!axis_reverse, eval)) || +				(!_right && eval_once(axis_type, eval)) ||  				(_right && !_right->_next && _right->_test == predicate_constant_one);  			xpath_node_set_raw ns; -			ns.set_type(axis_reverse ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted); +			ns.set_type(axis_type);  			if (_left)  			{ @@ -9040,13 +9126,13 @@ PUGI__NS_BEGIN  					if (axis != axis_self && size != 0) ns.set_type(xpath_node_set::type_unsorted);  					step_fill(ns, *it, stack.result, once, v); -					apply_predicates(ns, size, stack, eval); +					if (_right) apply_predicates(ns, size, stack, eval);  				}  			}  			else  			{  				step_fill(ns, c.n, stack.result, once, v); -				apply_predicates(ns, 0, stack, eval); +				if (_right) apply_predicates(ns, 0, stack, eval);  			}  			// child, attribute and self axes always generate unique set of nodes @@ -9524,9 +9610,10 @@ PUGI__NS_BEGIN  				const char_t* pos = find_substring(s.c_str(), p.c_str());  				if (!pos) return xpath_string(); -				const char_t* result = pos + p.length(); +				const char_t* rbegin = pos + p.length(); +				const char_t* rend = s.c_str() + s.length(); -				return s.uses_heap() ? xpath_string::from_heap(result, s.c_str() + s.length(), stack.result) : xpath_string::from_const(result); +				return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin);  			}  			case ast_func_substring_2: @@ -9547,8 +9634,9 @@ PUGI__NS_BEGIN  				assert(1 <= pos && pos <= s_length + 1);  				const char_t* rbegin = s.c_str() + (pos - 1); +				const char_t* rend = s.c_str() + s.length(); -				return s.uses_heap() ? xpath_string::from_heap(rbegin, s.c_str() + s.length(), stack.result) : xpath_string::from_const(rbegin); +				return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin);  			}  			case ast_func_substring_3: @@ -9582,18 +9670,20 @@ PUGI__NS_BEGIN  			{  				xpath_string s = string_value(c.n, stack.result); -				normalize_space(s.data(stack.result)); +				char_t* begin = s.data(stack.result); +				char_t* end = normalize_space(begin); -				return s; +				return xpath_string::from_heap_preallocated(begin, end);  			}  			case ast_func_normalize_space_1:  			{  				xpath_string s = _left->eval_string(c, stack); -				normalize_space(s.data(stack.result)); +				char_t* begin = s.data(stack.result); +				char_t* end = normalize_space(begin); -				return s; +				return xpath_string::from_heap_preallocated(begin, end);  			}  			case ast_func_translate: @@ -9606,18 +9696,20 @@ PUGI__NS_BEGIN  				xpath_string from = _right->eval_string(c, swapped_stack);  				xpath_string to = _right->_next->eval_string(c, swapped_stack); -				translate(s.data(stack.result), from.c_str(), to.c_str(), to.length()); +				char_t* begin = s.data(stack.result); +				char_t* end = translate(begin, from.c_str(), to.c_str(), to.length()); -				return s; +				return xpath_string::from_heap_preallocated(begin, end);  			}  			case ast_opt_translate_table:  			{  				xpath_string s = _left->eval_string(c, stack); -				translate_table(s.data(stack.result), _data.table); +				char_t* begin = s.data(stack.result); +				char_t* end = translate_table(begin, _data.table); -				return s; +				return xpath_string::from_heap_preallocated(begin, end);  			}  			case ast_variable: @@ -9687,7 +9779,7 @@ PUGI__NS_BEGIN  				// either expression is a number or it contains position() call; sort by document order  				if (_test != predicate_posinv) set.sort_do(); -				bool once = eval_once(set.type() == xpath_node_set::type_sorted, eval); +				bool once = eval_once(set.type(), eval);  				apply_predicate(set, 0, stack, once); diff --git a/src/pugixml.hpp b/src/pugixml.hpp index e252e16..9798b46 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -1,5 +1,5 @@  /** - * pugixml parser - version 1.4 + * pugixml parser - version 1.5   * --------------------------------------------------------   * Copyright (C) 2006-2014, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)   * Report bugs and download new versions at http://pugixml.org/ @@ -13,7 +13,7 @@  #ifndef PUGIXML_VERSION  // Define version macro; evaluates to major * 100 + minor so that it's safe to use in less-than comparisons -#	define PUGIXML_VERSION 140 +#	define PUGIXML_VERSION 150  #endif  // Include user configuration file (this can define various configuration macros) @@ -352,6 +352,7 @@ namespace pugi  		bool set_value(int rhs);  		bool set_value(unsigned int rhs);  		bool set_value(double rhs); +		bool set_value(float rhs);  		bool set_value(bool rhs);  	#ifdef PUGIXML_HAS_LONG_LONG @@ -364,6 +365,7 @@ namespace pugi  		xml_attribute& operator=(int rhs);  		xml_attribute& operator=(unsigned int rhs);  		xml_attribute& operator=(double rhs); +		xml_attribute& operator=(float rhs);  		xml_attribute& operator=(bool rhs);  	#ifdef PUGIXML_HAS_LONG_LONG @@ -431,7 +433,7 @@ namespace pugi  		const char_t* name() const;  		// Get node value, or "" if node is empty or it has no value -        // Note: For <node>text</node> node.value() does not return "text"! Use child_value() or text() methods to access text inside nodes. +		// Note: For <node>text</node> node.value() does not return "text"! Use child_value() or text() methods to access text inside nodes.  		const char_t* value() const;  		// Get attribute list @@ -694,6 +696,7 @@ namespace pugi  		bool set(int rhs);  		bool set(unsigned int rhs);  		bool set(double rhs); +		bool set(float rhs);  		bool set(bool rhs);  	#ifdef PUGIXML_HAS_LONG_LONG @@ -706,6 +709,7 @@ namespace pugi  		xml_text& operator=(int rhs);  		xml_text& operator=(unsigned int rhs);  		xml_text& operator=(double rhs); +		xml_text& operator=(float rhs);  		xml_text& operator=(bool rhs);  	#ifdef PUGIXML_HAS_LONG_LONG @@ -959,9 +963,12 @@ namespace pugi  		xml_parse_result load(std::basic_istream<wchar_t, std::char_traits<wchar_t> >& stream, unsigned int options = parse_default);  	#endif -		// Load document from zero-terminated string. No encoding conversions are applied. +		// (deprecated: use load_string instead) Load document from zero-terminated string. No encoding conversions are applied.  		xml_parse_result load(const char_t* contents, unsigned int options = parse_default); +		// Load document from zero-terminated string. No encoding conversions are applied. +		xml_parse_result load_string(const char_t* contents, unsigned int options = parse_default); +  		// Load document from file  		xml_parse_result load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);  		xml_parse_result load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); @@ -1326,6 +1333,13 @@ namespace std  #endif +// Make sure implementation is included in header-only mode +// Use macro expansion in #include to work around QMake (QTBUG-11923) +#if defined(PUGIXML_HEADER_ONLY) && !defined(PUGIXML_SOURCE) +#	define PUGIXML_SOURCE "pugixml.cpp" +#	include PUGIXML_SOURCE +#endif +  /**   * Copyright (c) 2006-2014 Arseny Kapoulkine   *  | 
