0
0
mirror of https://github.com/zeux/pugixml.git synced 2024-12-31 00:13:01 +08:00

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.
This commit is contained in:
Arseny Kapoulkine 2015-04-12 02:05:59 -07:00
parent 99afee1832
commit d6f7766172

View File

@ -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();
while (cursor.parent())
size_t offset = 0;
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);
}