diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/pugixml.cpp | 113 | 
1 files changed, 80 insertions, 33 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 251ba7f..7c640de 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -1088,11 +1088,11 @@ PUGI__NS_BEGIN  	#endif  	}; -	inline xml_allocator& get_allocator(const xml_node_struct* node) +	template <typename Object> inline xml_allocator& get_allocator(const Object* object)  	{ -		assert(node); +		assert(object); -		return *reinterpret_cast<xml_memory_page*>(node->header & xml_memory_page_pointer_mask)->allocator; +		return *reinterpret_cast<xml_memory_page*>(object->header & xml_memory_page_pointer_mask)->allocator;  	}  	template <typename Object> inline xml_document_struct& get_document(const Object* object) @@ -2235,9 +2235,6 @@ PUGI__NS_BEGIN  		assert(begin + size == end);  		(void)!end; - -		// zero-terminate -		buffer[size] = 0;  	}  #ifndef PUGIXML_NO_STL @@ -4383,6 +4380,15 @@ PUGI__NS_BEGIN  		}  	} +	PUGI__FN void node_copy_attribute(xml_attribute_struct* da, xml_attribute_struct* sa) +	{ +		xml_allocator& alloc = get_allocator(da); +		xml_allocator* shared_alloc = (&alloc == &get_allocator(sa)) ? &alloc : 0; + +		node_copy_string(da->name, da->header, xml_memory_page_name_allocated_mask, sa->name, sa->header, shared_alloc); +		node_copy_string(da->value, da->header, xml_memory_page_value_allocated_mask, sa->value, sa->header, shared_alloc); +	} +  	inline bool is_text_node(xml_node_struct* node)  	{  		xml_node_type type = PUGI__NODETYPE(node); @@ -4623,6 +4629,7 @@ PUGI__NS_BEGIN  		return status_ok;  	} +	// This function assumes that buffer has extra sizeof(char_t) writable bytes after size  	PUGI__FN size_t zero_terminate_buffer(void* buffer, size_t size, xml_encoding encoding)   	{  		// We only need to zero-terminate if encoding conversion does not do it for us @@ -4859,6 +4866,9 @@ PUGI__NS_BEGIN  		// second pass: convert to utf8  		as_utf8_end(result, size, str, length); +		// zero-terminate +		result[size] = 0; +  		return result;  	} @@ -5590,41 +5600,59 @@ namespace pugi  	PUGI__FN xml_attribute xml_node::append_copy(const xml_attribute& proto)  	{  		if (!proto) return xml_attribute(); +		if (!impl::allow_insert_attribute(type())) return xml_attribute(); -		xml_attribute result = append_attribute(proto.name()); -		result.set_value(proto.value()); +		xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); +		if (!a) return xml_attribute(); -		return result; +		impl::append_attribute(a._attr, _root); +		impl::node_copy_attribute(a._attr, proto._attr); + +		return a;  	}  	PUGI__FN xml_attribute xml_node::prepend_copy(const xml_attribute& proto)  	{  		if (!proto) return xml_attribute(); +		if (!impl::allow_insert_attribute(type())) return xml_attribute(); -		xml_attribute result = prepend_attribute(proto.name()); -		result.set_value(proto.value()); +		xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); +		if (!a) return xml_attribute(); -		return result; +		impl::prepend_attribute(a._attr, _root); +		impl::node_copy_attribute(a._attr, proto._attr); + +		return a;  	}  	PUGI__FN xml_attribute xml_node::insert_copy_after(const xml_attribute& proto, const xml_attribute& attr)  	{  		if (!proto) 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))); +		if (!a) return xml_attribute(); -		xml_attribute result = insert_attribute_after(proto.name(), attr); -		result.set_value(proto.value()); +		impl::insert_attribute_after(a._attr, attr._attr, _root); +		impl::node_copy_attribute(a._attr, proto._attr); -		return result; +		return a;  	}  	PUGI__FN xml_attribute xml_node::insert_copy_before(const xml_attribute& proto, const xml_attribute& attr)  	{  		if (!proto) 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 result = insert_attribute_before(proto.name(), attr); -		result.set_value(proto.value()); +		xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); +		if (!a) return xml_attribute(); -		return result; +		impl::insert_attribute_before(a._attr, attr._attr, _root); +		impl::node_copy_attribute(a._attr, proto._attr); + +		return a;  	}  	PUGI__FN xml_node xml_node::append_child(xml_node_type type_) @@ -5975,20 +6003,35 @@ namespace pugi  #ifndef PUGIXML_NO_STL  	PUGI__FN string_t xml_node::path(char_t delimiter) const  	{ -		xml_node cursor = *this; // Make a copy. -		 -		string_t result = cursor.name(); +		if (!_root) return string_t(); + +		size_t offset = 0; -		while (cursor.parent()) +		for (xml_node_struct* i = _root; i; i = i->parent)  		{ -			cursor = cursor.parent(); -			 -			string_t temp = cursor.name(); -			temp += delimiter; -			temp += result; -			result.swap(temp); +			offset += (i != _root); +			offset += i->name ? impl::strlength(i->name) : 0; +		} + +		string_t result; +		result.resize(offset); + +		for (xml_node_struct* j = _root; j; j = j->parent) +		{ +			if (j != _root) +				result[--offset] = delimiter; + +			if (j->name && *j->name) +			{ +				size_t length = impl::strlength(j->name); + +				offset -= length; +				memcpy(&result[offset], j->name, length * sizeof(char_t)); +			}  		} +		assert(offset == 0); +  		return result;  	}  #endif @@ -6825,12 +6868,14 @@ namespace pugi  	PUGI__FN bool xml_document::save_file(const char* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const  	{  		FILE* file = fopen(path_, (flags & format_save_file_text) ? "w" : "wb"); +  		return impl::save_file_impl(*this, file, indent, flags, encoding);  	}  	PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const  	{  		FILE* file = impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"); +  		return impl::save_file_impl(*this, file, indent, flags, encoding);  	} @@ -8351,7 +8396,7 @@ PUGI__NS_BEGIN  		}  	} -	PUGI__FN xpath_variable* get_variable_scratch(char_t (&buffer)[32], xpath_variable_set* set, const char_t* begin, const char_t* end) +	PUGI__FN bool get_variable_scratch(char_t (&buffer)[32], xpath_variable_set* set, const char_t* begin, const char_t* end, xpath_variable** out_result)  	{  		size_t length = static_cast<size_t>(end - begin);  		char_t* scratch = buffer; @@ -8360,19 +8405,19 @@ PUGI__NS_BEGIN  		{  			// need to make dummy on-heap copy  			scratch = static_cast<char_t*>(xml_memory::allocate((length + 1) * sizeof(char_t))); -			if (!scratch) return 0; +			if (!scratch) return false;  		}  		// copy string to zero-terminated buffer and perform lookup  		memcpy(scratch, begin, length * sizeof(char_t));  		scratch[length] = 0; -		xpath_variable* result = set->get(scratch); +		*out_result = set->get(scratch);  		// free dummy buffer  		if (scratch != buffer) xml_memory::deallocate(scratch); -		return result; +		return true;  	}  PUGI__NS_END @@ -10945,7 +10990,9 @@ PUGI__NS_BEGIN  				if (!_variables)  					throw_error("Unknown variable: variable set is not provided"); -				xpath_variable* var = get_variable_scratch(_scratch, _variables, name.begin, name.end); +				xpath_variable* var = 0; +				if (!get_variable_scratch(_scratch, _variables, name.begin, name.end, &var)) +					throw_error_oom();  				if (!var)  					throw_error("Unknown variable: variable set does not contain the given name");  | 
