diff options
| author | arseny.kapoulkine <arseny.kapoulkine@99668b35-9821-0410-8761-19e4c4f06640> | 2010-09-13 20:34:53 +0000 | 
|---|---|---|
| committer | arseny.kapoulkine <arseny.kapoulkine@99668b35-9821-0410-8761-19e4c4f06640> | 2010-09-13 20:34:53 +0000 | 
| commit | 628197f8c8d54c6ed3260ee4a2fe6b92b281aa0e (patch) | |
| tree | 479a6a491b240ab5b77c2e9f25a3dfd89e9a6af7 /src | |
| parent | 0f7684b5671f8fd9ac461f1c75c3a04ba13cb65f (diff) | |
XPath: Minor speed/memory improvements
git-svn-id: http://pugixml.googlecode.com/svn/trunk@726 99668b35-9821-0410-8761-19e4c4f06640
Diffstat (limited to 'src')
| -rw-r--r-- | src/pugixml.cpp | 85 | 
1 files changed, 49 insertions, 36 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 3e32217..1303939 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -4787,19 +4787,24 @@ namespace pugi  		void* reallocate(void* ptr, size_t old_size, size_t new_size)  		{ +			// align size so that we're able to store pointers in subsequent blocks +			old_size = (old_size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); +			new_size = (new_size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); +  			// we can only reallocate the last object -			assert(static_cast<char*>(ptr) + old_size == _root->data + _root_size); +			assert(ptr == 0 || static_cast<char*>(ptr) + old_size == _root->data + _root_size);  			// adjust root size so that we have not allocated the object at all -			_root_size -= old_size; -			bool only_object = (_root_size == 0); +			bool only_object = (_root_size == old_size); + +			if (ptr) _root_size -= old_size;  			// allocate a new version (this will obviously reuse the memory if possible)  			void* result = allocate(new_size);  			if (!result) return 0; // $$ out of memory  			// we have a new block -			if (result != ptr) +			if (result != ptr && ptr)  			{  				// copy old data  				assert(new_size > old_size); @@ -4975,12 +4980,13 @@ namespace  				size_t length = target_length + source_length;  				// allocate new buffer -				char_t* result = static_cast<char_t*>(alloc->allocate((length + 1) * sizeof(char_t))); +				char_t* result = static_cast<char_t*>(alloc->reallocate(_uses_heap ? const_cast<char_t*>(_buffer) : 0, (target_length + 1) * sizeof(char_t), (length + 1) * sizeof(char_t)));  				if (!result) return; // $$ out of memory -				// $$ reallocate -				// append both strings in the new buffer -				memcpy(result, _buffer, target_length * sizeof(char_t)); +				// append first string to the new buffer in case there was no reallocation +				if (!_uses_heap) memcpy(result, _buffer, target_length * sizeof(char_t)); + +				// append second string to the new buffer  				memcpy(result + target_length, o._buffer, source_length * sizeof(char_t));  				result[length] = 0; @@ -5874,21 +5880,8 @@ namespace  				size_t new_capacity = capacity + capacity / 2 + 1;  				// reallocate the old array or allocate a new one -				xpath_node* data = 0; - -				if (_begin) -				{ -					data = static_cast<xpath_node*>(alloc->reallocate(_begin, capacity * sizeof(xpath_node), new_capacity * sizeof(xpath_node))); -					if (!data) return; // $$ out of memory -				} -				else -				{ -					data = static_cast<xpath_node*>(alloc->allocate(new_capacity * sizeof(xpath_node))); -					if (!data) return; // $$ out of memory - -					memcpy(data, _begin, capacity * sizeof(xpath_node)); -				} - +				xpath_node* data = static_cast<xpath_node*>(alloc->reallocate(_begin, capacity * sizeof(xpath_node), new_capacity * sizeof(xpath_node))); +				if (!data) return; // $$ out of memory  				// finalize  				_begin = data; @@ -5899,6 +5892,28 @@ namespace  			*_end++ = node;  		} +		void append(const xpath_node* begin, const xpath_node* end, xpath_allocator* alloc) +		{ +			size_t size = static_cast<size_t>(_end - _begin); +			size_t capacity = static_cast<size_t>(_eos - _begin); +			size_t count = static_cast<size_t>(end - begin); + +			if (size + count > capacity) +			{ +				// reallocate the old array or allocate a new one +				xpath_node* data = static_cast<xpath_node*>(alloc->reallocate(_begin, capacity * sizeof(xpath_node), (size + count) * sizeof(xpath_node))); +				if (!data) return; // $$ out of memory + +				// finalize +				_begin = data; +				_end = data + size; +				_eos = data + size + count; +			} + +			memcpy(_end, begin, count * sizeof(xpath_node)); +			_end += count; +		} +  		void sort()  		{  			_type = xpath_sort(_begin, _end, _type, false); @@ -7419,7 +7434,11 @@ namespace pugi  				xpath_node_set_raw ns = _left->eval_node_set(c, stack);  				for (const xpath_node* it = ns.begin(); it != ns.end(); ++it) +				{ +					xpath_allocator_capture cri(stack.result); +  					r += convert_string_to_number(string_value(*it, stack.result).c_str()); +				}  				return r;  			} @@ -7488,7 +7507,7 @@ namespace pugi  			xpath_allocator_capture ct(stack.temp);  			// count the string number -			unsigned int count = 1; +			size_t count = 1;  			for (xpath_ast_node* nc = _right; nc; nc = nc->_next) count++;  			// gather all strings @@ -7513,7 +7532,7 @@ namespace pugi  			// get total length  			size_t length = 0; -			for (unsigned int i = 0; i < count; ++i) length += buffer[i].length(); +			for (size_t i = 0; i < count; ++i) length += buffer[i].length();  			// create final string  			char_t* result = static_cast<char_t*>(stack.result->allocate((length + 1) * sizeof(char_t))); @@ -7522,7 +7541,7 @@ namespace pugi  			{  				char_t* ri = result; -				for (unsigned int i = 0; i < count; ++i) +				for (size_t i = 0; i < count; ++i)  					for (const char_t* bi = buffer[i].c_str(); *bi; ++bi)  						*ri++ = *bi; @@ -7677,11 +7696,9 @@ namespace pugi  				assert(1 <= pos && pos <= end && end <= s_length + 1);  				const char_t* rbegin = s.c_str() + (pos - 1); +				const char_t* rend = s.c_str() + (end - 1); -				if (end == s_length + 1) -					return s.uses_heap() ? xpath_string(rbegin, stack.result) : xpath_string_const(rbegin); -				else -					return xpath_string(s.c_str() + (pos - 1), s.c_str() + (end - 1), stack.result); +				return (end == s_length + 1 && !s.uses_heap()) ? xpath_string_const(rbegin) : xpath_string(rbegin, rend, stack.result);  			}  			case ast_func_normalize_space_0: @@ -7771,9 +7788,7 @@ namespace pugi  				// we can optimize merging two sorted sets, but this is a very rare operation, so don't bother    		        rs.set_type(xpath_node_set::type_unsorted); -				for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) -					rs.push_back(*li, stack.result); -				 +				rs.append(ls.begin(), ls.end(), stack.result);  				rs.remove_duplicates();  				return rs; @@ -7866,9 +7881,7 @@ namespace pugi  					xpath_node_set_raw ns;  					ns.set_type(s.type()); - -					for (xpath_node_set::const_iterator i = s.begin(); i != s.end(); ++i) -						ns.push_back(*i, stack.result); +					ns.append(s.begin(), s.end(), stack.result);  					return ns;  				}  | 
