nsresult PredicateList::evaluatePredicates(txNodeSet* nodes, txIMatchContext* aContext) { NS_ASSERTION(nodes, "called evaluatePredicates with nullptr NodeSet"); nsresult rv = NS_OK; uint32_t i, len = mPredicates.Length(); for (i = 0; i < len && !nodes->isEmpty(); ++i) { txNodeSetContext predContext(nodes, aContext); /* * add nodes to newNodes that match the expression * or, if the result is a number, add the node with the right * position */ int32_t index = 0; while (predContext.hasNext()) { predContext.next(); RefPtr<txAExprResult> exprResult; rv = mPredicates[i]->evaluate(&predContext, getter_AddRefs(exprResult)); NS_ENSURE_SUCCESS(rv, rv); // handle default, [position() == numberValue()] if (exprResult->getResultType() == txAExprResult::NUMBER) { if ((double)predContext.position() == exprResult->numberValue()) { nodes->mark(index); } } else if (exprResult->booleanValue()) { nodes->mark(index); } ++index; } // sweep the non-marked nodes nodes->sweep(); } return NS_OK; }
bool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) { NS_ASSERTION(mNodeTest, "Internal error"); if (!mNodeTest->matches(aNode, aContext)) return false; txXPathTreeWalker walker(aNode); if ((!mIsAttr && txXPathNodeUtils::isAttribute(walker.getCurrentPosition())) || !walker.moveToParent()) { return false; } if (isEmpty()) { return true; } /* * Evaluate Predicates * * Copy all siblings/attributes matching mNodeTest to nodes * Up to the last Predicate do * Foreach node in nodes * evaluate Predicate with node as context node * if the result is a number, check the context position, * otherwise convert to bool * if result is true, copy node to newNodes * if aNode is not member of newNodes, return false * nodes = newNodes * * For the last Predicate, evaluate Predicate with aNode as * context node, if the result is a number, check the position, * otherwise return the result converted to boolean */ // Create the context node set for evaluating the predicates nsRefPtr<txNodeSet> nodes; nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes)); NS_ENSURE_SUCCESS(rv, false); bool hasNext = mIsAttr ? walker.moveToFirstAttribute() : walker.moveToFirstChild(); while (hasNext) { if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) { nodes->append(walker.getCurrentPosition()); } hasNext = mIsAttr ? walker.moveToNextAttribute() : walker.moveToNextSibling(); } Expr* predicate = mPredicates[0]; nsRefPtr<txNodeSet> newNodes; rv = aContext->recycler()->getNodeSet(getter_AddRefs(newNodes)); NS_ENSURE_SUCCESS(rv, false); PRUint32 i, predLen = mPredicates.Length(); for (i = 1; i < predLen; ++i) { newNodes->clear(); bool contextIsInPredicate = false; txNodeSetContext predContext(nodes, aContext); while (predContext.hasNext()) { predContext.next(); nsRefPtr<txAExprResult> exprResult; rv = predicate->evaluate(&predContext, getter_AddRefs(exprResult)); NS_ENSURE_SUCCESS(rv, false); switch(exprResult->getResultType()) { case txAExprResult::NUMBER: // handle default, [position() == numberValue()] if ((double)predContext.position() == exprResult->numberValue()) { const txXPathNode& tmp = predContext.getContextNode(); if (tmp == aNode) contextIsInPredicate = true; newNodes->append(tmp); } break; default: if (exprResult->booleanValue()) { const txXPathNode& tmp = predContext.getContextNode(); if (tmp == aNode) contextIsInPredicate = true; newNodes->append(tmp); } break; } } // Move new NodeSet to the current one nodes->clear(); nodes->append(*newNodes); if (!contextIsInPredicate) { return false; } predicate = mPredicates[i]; } txForwardContext evalContext(aContext, aNode, nodes); nsRefPtr<txAExprResult> exprResult; rv = predicate->evaluate(&evalContext, getter_AddRefs(exprResult)); NS_ENSURE_SUCCESS(rv, false); if (exprResult->getResultType() == txAExprResult::NUMBER) // handle default, [position() == numberValue()] return ((double)evalContext.position() == exprResult->numberValue()); return exprResult->booleanValue(); } // matches