From d6f7766172bd3dcd6b286888f5bdfdcb1953f3ba Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sun, 12 Apr 2015 02:05:59 -0700 Subject: Optimize xml_node::path() to use 1 allocation Instead of reallocating the string for every tree level just do two passes over the ancestor chain. --- src/pugixml.cpp | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'src/pugixml.cpp') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 6b3e87e..619cc7b 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -4056,6 +4056,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 @@ -5328,20 +5329,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 @@ -6188,12 +6204,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); } -- cgit v1.2.3