diff options
author | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2015-05-14 08:01:03 -0700 |
---|---|---|
committer | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2015-05-14 08:04:06 -0700 |
commit | f828eae3eaca02c9659d63cbcab65c9dd8e13869 (patch) | |
tree | 71347971f8e7c857f49f2f7a2d4ecaef390e939f /src/pugixml.cpp | |
parent | 01f627a4d75ae25850bc29df74112696da571326 (diff) |
Implement xml_node::attribute with a hint
Extra argument 'hint' is used to start the attribute lookup; if the attribute
is not found the lookup is restarted from the beginning of the attriubte list.
This allows to optimize attribute lookups if you need to get many attributes
from the node and can make assumptions about the likely ordering. The code is
correct regardless of the order, but it is faster than using vanilla lookups
if the order matches the calling order.
Fixes #30.
Diffstat (limited to 'src/pugixml.cpp')
-rw-r--r-- | src/pugixml.cpp | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index b1e81ad..1f23b44 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -5431,6 +5431,39 @@ namespace pugi return xml_node(); } + PUGI__FN xml_attribute xml_node::attribute(const char_t* name_, xml_attribute& hint_) const + { + xml_attribute_struct* hint = hint_._attr; + + // if hint is not an attribute of node, behavior is not defined + assert(!hint || (_root && impl::is_attribute_of(hint, _root))); + + if (!_root) return xml_attribute(); + + // optimistically search from hint up until the end + for (xml_attribute_struct* i = hint; i; i = i->next_attribute) + if (i->name && impl::strequal(name_, i->name)) + { + // update hint to maximize efficiency of searching for consecutive attributes + hint_._attr = i->next_attribute; + + return xml_attribute(i); + } + + // wrap around and search from the first attribute until the hint + // 'j' null pointer check is technically redundant, but it prevents a crash in case the assertion above fails + for (xml_attribute_struct* j = _root->first_attribute; j && j != hint; j = j->next_attribute) + if (j->name && impl::strequal(name_, j->name)) + { + // update hint to maximize efficiency of searching for consecutive attributes + hint_._attr = j->next_attribute; + + return xml_attribute(j); + } + + return xml_attribute(); + } + PUGI__FN xml_node xml_node::previous_sibling() const { if (!_root) return xml_node(); |