summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorArseny Kapoulkine <arseny.kapoulkine@gmail.com>2014-10-27 18:50:09 -0700
committerArseny Kapoulkine <arseny.kapoulkine@gmail.com>2014-10-27 18:50:09 -0700
commitc64d4820b142e6df93ccf612d0e4717159a36591 (patch)
tree67b41215c627fa43283fb1b9a3e14e1bd66fa946 /src
parentdbfe85a717b7ac8b9bd30eb51796811c0c651da9 (diff)
XPath: Optimize [position()=expr] and [last()]
To get more benefits from constant predicate/filter optimization we rewrite [position()=expr] predicates into [expr] for numeric expressions. Right now the rewrite is only for entire expressions - it may be beneficial to split complex expressions like [position()=constant and expr] into [constant][expr] but that is more complicated. last() does not depend on the node set contents so is "constant" as far as our optimization is concerned so we can evaluate it once.
Diffstat (limited to 'src')
-rw-r--r--src/pugixml.cpp10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp
index 67591a3..f0bfc31 100644
--- a/src/pugixml.cpp
+++ b/src/pugixml.cpp
@@ -9765,6 +9765,14 @@ PUGI__NS_BEGIN
if (_right) _right->optimize(alloc);
if (_next) _next->optimize(alloc);
+ // Rewrite [position()=expr] with [expr]
+ // Note that this step has to go before classification to recognize [position()=1]
+ if ((_type == ast_filter || _type == ast_predicate) &&
+ _right->_type == ast_op_equal && _right->_left->_type == ast_func_position && _right->_right->_rettype == xpath_type_number)
+ {
+ _right = _right->_right;
+ }
+
// Classify filter/predicate ops to perform various optimizations during evaluation
if (_type == ast_filter || _type == ast_predicate)
{
@@ -9772,7 +9780,7 @@ PUGI__NS_BEGIN
if (_right->_type == ast_number_constant && _right->_data.number == 1.0)
_test = predicate_constant_one;
- else if (_right->_rettype == xpath_type_number && (_right->_type == ast_number_constant || _right->_type == ast_variable))
+ else if (_right->_rettype == xpath_type_number && (_right->_type == ast_number_constant || _right->_type == ast_variable || _right->_type == ast_func_last))
_test = predicate_constant;
else if (_right->_rettype != xpath_type_number && _right->is_posinv_expr())
_test = predicate_posinv;