summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArseny Kapoulkine <arseny.kapoulkine@gmail.com>2015-04-12 02:05:59 -0700
committerArseny Kapoulkine <arseny.kapoulkine@gmail.com>2015-04-12 02:12:15 -0700
commitd6f7766172bd3dcd6b286888f5bdfdcb1953f3ba (patch)
tree68cc60af797c45b68b5ed6700bf4daecf1bfa0fb
parent99afee183225f6f33f3289030c992738ccaf13fe (diff)
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.
-rw-r--r--src/pugixml.cpp38
1 files changed, 28 insertions, 10 deletions
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);
}