XPath: Minor ast_step processing refactoring

git-svn-id: http://pugixml.googlecode.com/svn/trunk@717 99668b35-9821-0410-8761-19e4c4f06640
This commit is contained in:
arseny.kapoulkine 2010-09-12 20:50:17 +00:00
parent cae6c066b7
commit 030e9da0d4

View File

@ -6942,81 +6942,42 @@ namespace pugi
} }
} }
template <class T> void step_do(xpath_node_set& ns, const xpath_context& c, T v) template <class T> xpath_node_set step_do(const xpath_context& c, T v)
{ {
const axis_t axis = T::axis; const axis_t axis = T::axis;
const bool attributes = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_descendant_or_self || axis == axis_following || axis == axis_parent || axis == axis_preceding || axis == axis_self);
assert(ns.empty()); xpath_node_set ns;
switch (axis) if (_left)
{ {
case axis_ancestor: xpath_node_set s = _left->eval_node_set(c);
case axis_ancestor_or_self:
case axis_descendant_or_self:
case axis_following:
case axis_parent:
case axis_preceding:
case axis_self:
if (_left)
{
xpath_node_set s = _left->eval_node_set(c);
for (xpath_node_set::const_iterator it = s.begin(); it != s.end(); ++it)
{
size_t size = ns.size();
if (it->node()) for (xpath_node_set::const_iterator it = s.begin(); it != s.end(); ++it)
step_fill(ns, it->node(), v);
else
step_fill(ns, it->attribute(), it->parent(), v);
apply_predicates(ns, size);
}
}
else
{ {
if (c.n.node()) step_fill(ns, c.n.node(), v); size_t size = ns.size();
else step_fill(ns, c.n.attribute(), c.n.parent(), v);
apply_predicates(ns, 0); if (it->node())
} step_fill(ns, it->node(), v);
else if (attributes)
break; step_fill(ns, it->attribute(), it->parent(), v);
case axis_following_sibling:
case axis_preceding_sibling:
case axis_attribute:
case axis_child:
case axis_descendant:
if (_left)
{
xpath_node_set s = _left->eval_node_set(c);
for (xpath_node_set::const_iterator it = s.begin(); it != s.end(); ++it)
{
size_t size = ns.size();
if (it->node()) apply_predicates(ns, size);
step_fill(ns, it->node(), v);
apply_predicates(ns, size);
}
} }
else if (c.n.node())
{
step_fill(ns, c.n.node(), v);
apply_predicates(ns, 0);
}
break;
case axis_namespace:
break;
default:
assert(!"Unimplemented axis");
} }
else
{
if (c.n.node())
step_fill(ns, c.n.node(), v);
else if (attributes)
step_fill(ns, c.n.attribute(), c.n.parent(), v);
apply_predicates(ns, 0);
}
ns.remove_duplicates();
return ns;
} }
public: public:
@ -7559,66 +7520,48 @@ namespace pugi
case ast_step: case ast_step:
{ {
xpath_node_set ns;
switch (_axis) switch (_axis)
{ {
case axis_ancestor: case axis_ancestor:
step_do(ns, c, axis_to_type<axis_ancestor>()); return step_do(c, axis_to_type<axis_ancestor>());
break;
case axis_ancestor_or_self: case axis_ancestor_or_self:
step_do(ns, c, axis_to_type<axis_ancestor_or_self>()); return step_do(c, axis_to_type<axis_ancestor_or_self>());
break;
case axis_attribute: case axis_attribute:
step_do(ns, c, axis_to_type<axis_attribute>()); return step_do(c, axis_to_type<axis_attribute>());
break;
case axis_child: case axis_child:
step_do(ns, c, axis_to_type<axis_child>()); return step_do(c, axis_to_type<axis_child>());
break;
case axis_descendant: case axis_descendant:
step_do(ns, c, axis_to_type<axis_descendant>()); return step_do(c, axis_to_type<axis_descendant>());
break;
case axis_descendant_or_self: case axis_descendant_or_self:
step_do(ns, c, axis_to_type<axis_descendant_or_self>()); return step_do(c, axis_to_type<axis_descendant_or_self>());
break;
case axis_following: case axis_following:
step_do(ns, c, axis_to_type<axis_following>()); return step_do(c, axis_to_type<axis_following>());
break;
case axis_following_sibling: case axis_following_sibling:
step_do(ns, c, axis_to_type<axis_following_sibling>()); return step_do(c, axis_to_type<axis_following_sibling>());
break;
case axis_namespace: case axis_namespace:
step_do(ns, c, axis_to_type<axis_namespace>()); // namespaced axis is not supported
break; return xpath_node_set();
case axis_parent: case axis_parent:
step_do(ns, c, axis_to_type<axis_parent>()); return step_do(c, axis_to_type<axis_parent>());
break;
case axis_preceding: case axis_preceding:
step_do(ns, c, axis_to_type<axis_preceding>()); return step_do(c, axis_to_type<axis_preceding>());
break;
case axis_preceding_sibling: case axis_preceding_sibling:
step_do(ns, c, axis_to_type<axis_preceding_sibling>()); return step_do(c, axis_to_type<axis_preceding_sibling>());
break;
case axis_self: case axis_self:
step_do(ns, c, axis_to_type<axis_self>()); return step_do(c, axis_to_type<axis_self>());
break;
} }
ns.remove_duplicates();
return ns;
} }
case ast_step_root: case ast_step_root: