XPath: Extend the descendant-or-self optimization
Use descendant-or-self::node() transformation for self, descendant and descendant-or-self axis. Self axis should be semi-frequent; descendant axes should not really be used with // but if they ever are the complexity of the step becomes quadratic so it's better to optimize this if possible. git-svn-id: https://pugixml.googlecode.com/svn/trunk@1063 99668b35-9821-0410-8761-19e4c4f06640
This commit is contained in:
parent
45e0c726f0
commit
72ec01c5f6
@ -9613,12 +9613,17 @@ PUGI__NS_BEGIN
|
|||||||
|
|
||||||
// Replace descendant-or-self::node()/child::foo with descendant::foo
|
// Replace descendant-or-self::node()/child::foo with descendant::foo
|
||||||
// The former is a full form of //foo, the latter is much faster since it executes the node test immediately
|
// The former is a full form of //foo, the latter is much faster since it executes the node test immediately
|
||||||
|
// Do a similar kind of replacement for self/descendant/descendant-or-self axes
|
||||||
// Note that we only replace positionally invariant steps (//foo[1] != /descendant::foo[1])
|
// Note that we only replace positionally invariant steps (//foo[1] != /descendant::foo[1])
|
||||||
if (_type == ast_step && _axis == axis_child && _left &&
|
if (_type == ast_step && (_axis == axis_child || _axis == axis_self || _axis == axis_descendant || _axis == axis_descendant_or_self) && _left &&
|
||||||
_left->_type == ast_step && _left->_axis == axis_descendant_or_self && _left->_test == nodetest_type_node && !_left->_right &&
|
_left->_type == ast_step && _left->_axis == axis_descendant_or_self && _left->_test == nodetest_type_node && !_left->_right &&
|
||||||
is_posinv_step())
|
is_posinv_step())
|
||||||
{
|
{
|
||||||
_axis = axis_descendant;
|
if (_axis == axis_child || _axis == axis_descendant)
|
||||||
|
_axis = axis_descendant;
|
||||||
|
else
|
||||||
|
_axis = axis_descendant_or_self;
|
||||||
|
|
||||||
_left = _left->_left;
|
_left = _left->_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -531,6 +531,21 @@ TEST_XML(xpath_paths_descendant_optimize, "<node><para><para/><para/><para><para
|
|||||||
CHECK_XPATH_NODESET(doc, STR("/descendant-or-self::node()[3]/child::para")) % 4 % 5 % 6;
|
CHECK_XPATH_NODESET(doc, STR("/descendant-or-self::node()[3]/child::para")) % 4 % 5 % 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_XML(xpath_paths_descendant_optimize_axes, "<node><para><para/><para/><para><para/></para></para><para/></node>")
|
||||||
|
{
|
||||||
|
CHECK_XPATH_NODESET(doc, STR("//.")) % 1 % 2 % 3 % 4 % 5 % 6 % 7 % 8;
|
||||||
|
CHECK_XPATH_NODESET(doc, STR("//descendant::*")) % 2 % 3 % 4 % 5 % 6 % 7 % 8;
|
||||||
|
CHECK_XPATH_NODESET(doc, STR("//descendant-or-self::*")) % 2 % 3 % 4 % 5 % 6 % 7 % 8;
|
||||||
|
|
||||||
|
CHECK_XPATH_NODESET(doc, STR("//..")) % 1 % 2 % 3 % 6;
|
||||||
|
CHECK_XPATH_NODESET(doc, STR("//ancestor::*")) % 2 % 3 % 6;
|
||||||
|
CHECK_XPATH_NODESET(doc, STR("//ancestor-or-self::*")) % 2 % 3 % 4 % 5 % 6 % 7 % 8;
|
||||||
|
CHECK_XPATH_NODESET(doc, STR("//preceding-sibling::*")) % 3 % 4 % 5;
|
||||||
|
CHECK_XPATH_NODESET(doc, STR("//following-sibling::*")) % 5 % 6 % 8;
|
||||||
|
CHECK_XPATH_NODESET(doc, STR("//preceding::*")) % 3 % 4 % 5 % 6 % 7;
|
||||||
|
CHECK_XPATH_NODESET(doc, STR("//following::*")) % 5 % 6 % 7 % 8;
|
||||||
|
}
|
||||||
|
|
||||||
TEST_XML(xpath_paths_descendant_optimize_last, "<node><para><para/><para/><para><para/></para></para><para/></node>")
|
TEST_XML(xpath_paths_descendant_optimize_last, "<node><para><para/><para/><para><para/></para></para><para/></node>")
|
||||||
{
|
{
|
||||||
CHECK_XPATH_NODESET(doc, STR("//para[last()]")) % 6 % 7 % 8;
|
CHECK_XPATH_NODESET(doc, STR("//para[last()]")) % 6 % 7 % 8;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user