diff options
| author | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2015-04-21 21:27:44 -0700 | 
|---|---|---|
| committer | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2015-04-21 21:27:44 -0700 | 
| commit | f9983ea2ed47811ad5a7e41b816642615cbd674f (patch) | |
| tree | c20551f1a314ee5776680d9171388cfa5f8bd95a /src | |
| parent | cb786665d44598cbaff721e50d6a56b7538789e5 (diff) | |
| parent | a6cc636a6b0d531686311b5666ea77225b10903e (diff) | |
Merge branch 'master' into compact
Diffstat (limited to 'src')
| -rw-r--r-- | src/pugixml.cpp | 261 | ||||
| -rw-r--r-- | src/pugixml.hpp | 47 | 
2 files changed, 263 insertions, 45 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 5c39775..b2c13f5 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -2235,6 +2235,7 @@ PUGI__NS_BEGIN  		assert(begin + size == end);  		(void)!end; +		(void)!size;  	}  #ifndef PUGIXML_NO_STL @@ -3663,11 +3664,6 @@ PUGI__NS_BEGIN  			PUGI__STATIC_ASSERT(bufcapacity >= 8);  		} -		~xml_buffered_writer() -		{ -			flush(); -		} -  		size_t flush()  		{  			flush(buffer, bufsize); @@ -4028,13 +4024,23 @@ PUGI__NS_BEGIN  		}  	} -	PUGI__FN void node_output_attributes(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) +	PUGI__FN void node_output_attributes(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth)  	{  		const char_t* default_name = PUGIXML_TEXT(":anonymous");  		for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute)  		{ -			writer.write(' '); +			if ((flags & (format_indent_attributes | format_raw)) == format_indent_attributes) +			{ +				writer.write('\n'); + +				text_output_indent(writer, indent, indent_length, depth + 1); +			} +			else +			{ +				writer.write(' '); +			} +  			writer.write_string(a->name ? a->name : default_name);  			writer.write('=', '"'); @@ -4045,7 +4051,7 @@ PUGI__NS_BEGIN  		}  	} -	PUGI__FN bool node_output_start(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) +	PUGI__FN bool node_output_start(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth)  	{  		const char_t* default_name = PUGIXML_TEXT(":anonymous");  		const char_t* name = node->contents ? node->contents : default_name; @@ -4054,7 +4060,7 @@ PUGI__NS_BEGIN  		writer.write_string(name);  		if (node->first_attribute) -			node_output_attributes(writer, node, flags); +			node_output_attributes(writer, node, indent, indent_length, flags, depth);  		if (!node->first_child)  		{ @@ -4114,7 +4120,7 @@ PUGI__NS_BEGIN  			case node_declaration:  				writer.write('<', '?');  				writer.write_string(node->contents ? node->contents : default_name); -				node_output_attributes(writer, node, flags); +				node_output_attributes(writer, node, PUGIXML_TEXT(""), 0, flags | format_raw, 0);  				writer.write('?', '>');  				break; @@ -4144,7 +4150,7 @@ PUGI__NS_BEGIN  	PUGI__FN void node_output(xml_buffered_writer& writer, xml_node_struct* root, const char_t* indent, unsigned int flags, unsigned int depth)  	{ -		size_t indent_length = ((flags & (format_indent | format_raw)) == format_indent) ? strlength(indent) : 0; +		size_t indent_length = ((flags & (format_indent | format_indent_attributes)) && (flags & format_raw) == 0) ? strlength(indent) : 0;  		unsigned int indent_flags = indent_indent;  		xml_node_struct* node = root; @@ -4172,7 +4178,7 @@ PUGI__NS_BEGIN  				{  					indent_flags = indent_newline | indent_indent; -					if (node_output_start(writer, node, flags)) +					if (node_output_start(writer, node, indent, indent_length, flags, depth))  					{  						node = node->first_child;  						depth++; @@ -6145,6 +6151,8 @@ namespace pugi  		impl::xml_buffered_writer buffered_writer(writer, encoding);  		impl::node_output(buffered_writer, _root, indent, flags, depth); + +		buffered_writer.flush();  	}  #ifndef PUGIXML_NO_STL @@ -6844,6 +6852,8 @@ namespace pugi  		}  		impl::node_output(buffered_writer, _root, indent, flags, 0); + +		buffered_writer.flush();  	}  #ifndef PUGIXML_NO_STL @@ -8265,7 +8275,7 @@ PUGI__NS_BEGIN  	struct xpath_variable_boolean: xpath_variable  	{ -		xpath_variable_boolean(): value(false) +		xpath_variable_boolean(): xpath_variable(xpath_type_boolean), value(false)  		{  		} @@ -8275,7 +8285,7 @@ PUGI__NS_BEGIN  	struct xpath_variable_number: xpath_variable  	{ -		xpath_variable_number(): value(0) +		xpath_variable_number(): xpath_variable(xpath_type_number), value(0)  		{  		} @@ -8285,7 +8295,7 @@ PUGI__NS_BEGIN  	struct xpath_variable_string: xpath_variable  	{ -		xpath_variable_string(): value(0) +		xpath_variable_string(): xpath_variable(xpath_type_string), value(0)  		{  		} @@ -8300,6 +8310,10 @@ PUGI__NS_BEGIN  	struct xpath_variable_node_set: xpath_variable  	{ +		xpath_variable_node_set(): xpath_variable(xpath_type_node_set) +		{ +		} +  		xpath_node_set value;  		char_t name[1];  	}; @@ -8393,6 +8407,28 @@ PUGI__NS_BEGIN  		}  	} +	PUGI__FN bool copy_xpath_variable(xpath_variable* lhs, const xpath_variable* rhs) +	{ +		switch (rhs->type()) +		{ +		case xpath_type_node_set: +			return lhs->set(static_cast<const xpath_variable_node_set*>(rhs)->value); + +		case xpath_type_number: +			return lhs->set(static_cast<const xpath_variable_number*>(rhs)->value); + +		case xpath_type_string: +			return lhs->set(static_cast<const xpath_variable_string*>(rhs)->value); + +		case xpath_type_boolean: +			return lhs->set(static_cast<const xpath_variable_boolean*>(rhs)->value); + +		default: +			assert(!"Invalid variable type"); +			return false; +		} +	} +  	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); @@ -11664,7 +11700,7 @@ namespace pugi  	}  #endif -	PUGI__FN void xpath_node_set::_assign(const_iterator begin_, const_iterator end_) +	PUGI__FN void xpath_node_set::_assign(const_iterator begin_, const_iterator end_, type_t type_)  	{  		assert(begin_ <= end_); @@ -11680,6 +11716,7 @@ namespace pugi  			_begin = &_storage;  			_end = &_storage + size_; +			_type = type_;  		}  		else  		{ @@ -11703,38 +11740,72 @@ namespace pugi  			// finalize  			_begin = storage;  			_end = storage + size_; +			_type = type_;  		}  	} +#if __cplusplus >= 201103 +	PUGI__FN void xpath_node_set::_move(xpath_node_set& rhs) +	{ +		_type = rhs._type; +		_storage = rhs._storage; +		_begin = (rhs._begin == &rhs._storage) ? &_storage : rhs._begin; +		_end = _begin + (rhs._end - rhs._begin); + +		rhs._type = type_unsorted; +		rhs._begin = &rhs._storage; +		rhs._end = rhs._begin; +	} +#endif +  	PUGI__FN xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(&_storage), _end(&_storage)  	{  	} -	PUGI__FN xpath_node_set::xpath_node_set(const_iterator begin_, const_iterator end_, type_t type_): _type(type_), _begin(&_storage), _end(&_storage) +	PUGI__FN xpath_node_set::xpath_node_set(const_iterator begin_, const_iterator end_, type_t type_): _type(type_unsorted), _begin(&_storage), _end(&_storage)  	{ -		_assign(begin_, end_); +		_assign(begin_, end_, type_);  	}  	PUGI__FN xpath_node_set::~xpath_node_set()  	{ -		if (_begin != &_storage) impl::xml_memory::deallocate(_begin); +		if (_begin != &_storage) +			impl::xml_memory::deallocate(_begin);  	} -	PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(ns._type), _begin(&_storage), _end(&_storage) +	PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(type_unsorted), _begin(&_storage), _end(&_storage)  	{ -		_assign(ns._begin, ns._end); +		_assign(ns._begin, ns._end, ns._type);  	}  	PUGI__FN xpath_node_set& xpath_node_set::operator=(const xpath_node_set& ns)  	{  		if (this == &ns) return *this; -		 -		_type = ns._type; -		_assign(ns._begin, ns._end); + +		_assign(ns._begin, ns._end, ns._type);  		return *this;  	} +#if __cplusplus >= 201103 +	PUGI__FN xpath_node_set::xpath_node_set(xpath_node_set&& rhs): _type(type_unsorted), _begin(&_storage), _end(&_storage) +	{ +		_move(rhs); +	} + +	PUGI__FN xpath_node_set& xpath_node_set::operator=(xpath_node_set&& rhs) +	{ +		if (this == &rhs) return *this; + +		if (_begin != &_storage) +			impl::xml_memory::deallocate(_begin); + +		_move(rhs); + +		return *this; +	} +#endif +  	PUGI__FN xpath_node_set::type_t xpath_node_set::type() const  	{  		return _type; @@ -11790,7 +11861,7 @@ namespace pugi  		return error ? error : "No error";  	} -	PUGI__FN xpath_variable::xpath_variable(): _type(xpath_type_none), _next(0) +	PUGI__FN xpath_variable::xpath_variable(xpath_value_type type_): _type(type_), _next(0)  	{  	} @@ -11889,27 +11960,80 @@ namespace pugi  	PUGI__FN xpath_variable_set::xpath_variable_set()  	{ -		for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) _data[i] = 0; +		for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) +			_data[i] = 0;  	}  	PUGI__FN xpath_variable_set::~xpath_variable_set()  	{  		for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) +			_destroy(_data[i]); +	} + +	PUGI__FN xpath_variable_set::xpath_variable_set(const xpath_variable_set& rhs) +	{ +		for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) +			_data[i] = 0; + +		_assign(rhs); +	} + +	PUGI__FN xpath_variable_set& xpath_variable_set::operator=(const xpath_variable_set& rhs) +	{ +		if (this == &rhs) return *this; + +		_assign(rhs); + +		return *this; +	} + +#if __cplusplus >= 201103 +	PUGI__FN xpath_variable_set::xpath_variable_set(xpath_variable_set&& rhs) +	{ +		for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i)  		{ -			xpath_variable* var = _data[i]; +			_data[i] = rhs._data[i]; +			rhs._data[i] = 0; +		} +	} -			while (var) -			{ -				xpath_variable* next = var->_next; +	PUGI__FN xpath_variable_set& xpath_variable_set::operator=(xpath_variable_set&& rhs) +	{ +		for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) +		{ +			_destroy(_data[i]); -				impl::delete_xpath_variable(var->_type, var); +			_data[i] = rhs._data[i]; +			rhs._data[i] = 0; +		} -				var = next; -			} +		return *this; +	} +#endif + +	PUGI__FN void xpath_variable_set::_assign(const xpath_variable_set& rhs) +	{ +		xpath_variable_set temp; + +		for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) +			if (rhs._data[i] && !_clone(rhs._data[i], &temp._data[i])) +				return; + +		_swap(temp); +	} + +	PUGI__FN void xpath_variable_set::_swap(xpath_variable_set& rhs) +	{ +		for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) +		{ +			xpath_variable* chain = _data[i]; + +			_data[i] = rhs._data[i]; +			rhs._data[i] = chain;  		}  	} -	PUGI__FN xpath_variable* xpath_variable_set::find(const char_t* name) const +	PUGI__FN xpath_variable* xpath_variable_set::_find(const char_t* name) const  	{  		const size_t hash_size = sizeof(_data) / sizeof(_data[0]);  		size_t hash = impl::hash_string(name) % hash_size; @@ -11922,6 +12046,45 @@ namespace pugi  		return 0;  	} +	PUGI__FN bool xpath_variable_set::_clone(xpath_variable* var, xpath_variable** out_result) +	{ +		xpath_variable* last = 0; + +		while (var) +		{ +			// allocate storage for new variable +			xpath_variable* nvar = impl::new_xpath_variable(var->_type, var->name()); +			if (!nvar) return false; + +			// link the variable to the result immediately to handle failures gracefully +			if (last) +				last->_next = nvar; +			else +				*out_result = nvar; + +			last = nvar; + +			// copy the value; this can fail due to out-of-memory conditions +			if (!impl::copy_xpath_variable(nvar, var)) return false; + +			var = var->_next; +		} + +		return true; +	} + +	PUGI__FN void xpath_variable_set::_destroy(xpath_variable* var) +	{ +		while (var) +		{ +			xpath_variable* next = var->_next; + +			impl::delete_xpath_variable(var->_type, var); + +			var = next; +		} +	} +  	PUGI__FN xpath_variable* xpath_variable_set::add(const char_t* name, xpath_value_type type)  	{  		const size_t hash_size = sizeof(_data) / sizeof(_data[0]); @@ -11937,7 +12100,6 @@ namespace pugi  		if (result)  		{ -			result->_type = type;  			result->_next = _data[hash];  			_data[hash] = result; @@ -11972,12 +12134,12 @@ namespace pugi  	PUGI__FN xpath_variable* xpath_variable_set::get(const char_t* name)  	{ -		return find(name); +		return _find(name);  	}  	PUGI__FN const xpath_variable* xpath_variable_set::get(const char_t* name) const  	{ -		return find(name); +		return _find(name);  	}  	PUGI__FN xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(0) @@ -12008,12 +12170,37 @@ namespace pugi  		}  	} +	PUGI__FN xpath_query::xpath_query(): _impl(0) +	{ +	} +  	PUGI__FN xpath_query::~xpath_query()  	{  		if (_impl)  			impl::xpath_query_impl::destroy(static_cast<impl::xpath_query_impl*>(_impl));  	} +#if __cplusplus >= 201103 +	PUGI__FN xpath_query::xpath_query(xpath_query&& rhs) +	{ +		_impl = rhs._impl; +		rhs._impl = 0; +	} + +	xpath_query& xpath_query::operator=(xpath_query&& rhs) +	{ +		if (this == &rhs) return *this; + +		if (_impl) +			impl::xpath_query_impl::destroy(static_cast<impl::xpath_query_impl*>(_impl)); + +		_impl = rhs._impl; +		rhs._impl = 0; + +		return *this; +	} +#endif +  	PUGI__FN xpath_value_type xpath_query::return_type() const  	{  		if (!_impl) return xpath_type_none; diff --git a/src/pugixml.hpp b/src/pugixml.hpp index d59f864..0f79fb7 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -65,7 +65,7 @@  // If the platform is known to have long long support, enable long long functions  #ifndef PUGIXML_HAS_LONG_LONG -#	if defined(__cplusplus) && __cplusplus >= 201103 +#	if __cplusplus >= 201103  #		define PUGIXML_HAS_LONG_LONG  #	elif defined(_MSC_VER) && _MSC_VER >= 1400  #		define PUGIXML_HAS_LONG_LONG @@ -203,10 +203,13 @@ namespace pugi  	// Open file using text mode in xml_document::save_file. This enables special character (i.e. new-line) conversions on some systems. This flag is off by default.  	const unsigned int format_save_file_text = 0x20; +	// Write every attribute on a new line with appropriate indentation. This flag is off by default. +	const unsigned int format_indent_attributes = 0x40; +  	// The default set of formatting flags.  	// Nodes are indented depending on their depth in DOM tree, a default declaration is output if document has none.  	const unsigned int format_default = format_indent; -		 +  	// Forward declarations  	struct xml_attribute_struct;  	struct xml_node_struct; @@ -1040,7 +1043,7 @@ namespace pugi  		xpath_value_type _type;  		xpath_variable* _next; -		xpath_variable(); +		xpath_variable(xpath_value_type type);  		// Non-copyable semantics  		xpath_variable(const xpath_variable&); @@ -1072,17 +1075,29 @@ namespace pugi  	private:  		xpath_variable* _data[64]; -		// Non-copyable semantics -		xpath_variable_set(const xpath_variable_set&); -		xpath_variable_set& operator=(const xpath_variable_set&); +		void _assign(const xpath_variable_set& rhs); +		void _swap(xpath_variable_set& rhs); -		xpath_variable* find(const char_t* name) const; +		xpath_variable* _find(const char_t* name) const; + +		static bool _clone(xpath_variable* var, xpath_variable** out_result); +		static void _destroy(xpath_variable* var);  	public:  		// Default constructor/destructor  		xpath_variable_set();  		~xpath_variable_set(); +		// Copy constructor/assignment operator +		xpath_variable_set(const xpath_variable_set& rhs); +		xpath_variable_set& operator=(const xpath_variable_set& rhs); + +	#if __cplusplus >= 201103 +		// Move semantics support +		xpath_variable_set(xpath_variable_set&& rhs); +		xpath_variable_set& operator=(xpath_variable_set&& rhs); +	#endif +  		// Add a new variable or get the existing one, if the types match  		xpath_variable* add(const char_t* name, xpath_value_type type); @@ -1115,9 +1130,18 @@ namespace pugi  		// If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors.  		explicit xpath_query(const char_t* query, xpath_variable_set* variables = 0); +		// Constructor +		xpath_query(); +  		// Destructor  		~xpath_query(); +	#if __cplusplus >= 201103 +		// Move semantics support +		xpath_query(xpath_query&& rhs); +		xpath_query& operator=(xpath_query&& rhs); +	#endif +  		// Get query expression return type  		xpath_value_type return_type() const; @@ -1253,6 +1277,12 @@ namespace pugi  		xpath_node_set(const xpath_node_set& ns);  		xpath_node_set& operator=(const xpath_node_set& ns); +	#if __cplusplus >= 201103 +		// Move semantics support +		xpath_node_set(xpath_node_set&& rhs); +		xpath_node_set& operator=(xpath_node_set&& rhs); +	#endif +  		// Get collection type  		type_t type() const; @@ -1283,7 +1313,8 @@ namespace pugi  		xpath_node* _begin;  		xpath_node* _end; -		void _assign(const_iterator begin, const_iterator end); +		void _assign(const_iterator begin, const_iterator end, type_t type); +		void _move(xpath_node_set& rhs);  	};  #endif  | 
