123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /*
- Implementation of an XPath LocationStep
- */
- #include "txExpr.h"
- #include "txIXPathContext.h"
- #include "txNodeSet.h"
- #include "txXPathTreeWalker.h"
- //-----------------------------/
- //- Virtual methods from Expr -/
- //-----------------------------/
- /**
- * Evaluates this Expr based on the given context node and processor state
- * @param context the context node for evaluation of this Expr
- * @param ps the ProcessorState containing the stack information needed
- * for evaluation
- * @return the result of the evaluation
- * @see Expr
- **/
- nsresult
- LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
- {
- NS_ASSERTION(aContext, "internal error");
- *aResult = nullptr;
- RefPtr<txNodeSet> nodes;
- nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes));
- NS_ENSURE_SUCCESS(rv, rv);
- txXPathTreeWalker walker(aContext->getContextNode());
- switch (mAxisIdentifier) {
- case ANCESTOR_AXIS:
- {
- if (!walker.moveToParent()) {
- break;
- }
- MOZ_FALLTHROUGH;
- }
- case ANCESTOR_OR_SELF_AXIS:
- {
- nodes->setReverse();
- do {
- if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
- nodes->append(walker.getCurrentPosition());
- }
- } while (walker.moveToParent());
- break;
- }
- case ATTRIBUTE_AXIS:
- {
- if (!walker.moveToFirstAttribute()) {
- break;
- }
- do {
- if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
- nodes->append(walker.getCurrentPosition());
- }
- } while (walker.moveToNextAttribute());
- break;
- }
- case DESCENDANT_OR_SELF_AXIS:
- {
- if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
- nodes->append(walker.getCurrentPosition());
- }
- MOZ_FALLTHROUGH;
- }
- case DESCENDANT_AXIS:
- {
- fromDescendants(walker.getCurrentPosition(), aContext, nodes);
- break;
- }
- case FOLLOWING_AXIS:
- {
- if (txXPathNodeUtils::isAttribute(walker.getCurrentPosition())) {
- walker.moveToParent();
- fromDescendants(walker.getCurrentPosition(), aContext, nodes);
- }
- bool cont = true;
- while (!walker.moveToNextSibling()) {
- if (!walker.moveToParent()) {
- cont = false;
- break;
- }
- }
- while (cont) {
- if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
- nodes->append(walker.getCurrentPosition());
- }
- fromDescendants(walker.getCurrentPosition(), aContext, nodes);
- while (!walker.moveToNextSibling()) {
- if (!walker.moveToParent()) {
- cont = false;
- break;
- }
- }
- }
- break;
- }
- case FOLLOWING_SIBLING_AXIS:
- {
- while (walker.moveToNextSibling()) {
- if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
- nodes->append(walker.getCurrentPosition());
- }
- }
- break;
- }
- case NAMESPACE_AXIS: //-- not yet implemented
- #if 0
- // XXX DEBUG OUTPUT
- cout << "namespace axis not yet implemented"<<endl;
- #endif
- break;
- case PARENT_AXIS :
- {
- if (walker.moveToParent() &&
- mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
- nodes->append(walker.getCurrentPosition());
- }
- break;
- }
- case PRECEDING_AXIS:
- {
- nodes->setReverse();
- bool cont = true;
- while (!walker.moveToPreviousSibling()) {
- if (!walker.moveToParent()) {
- cont = false;
- break;
- }
- }
- while (cont) {
- fromDescendantsRev(walker.getCurrentPosition(), aContext, nodes);
- if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
- nodes->append(walker.getCurrentPosition());
- }
- while (!walker.moveToPreviousSibling()) {
- if (!walker.moveToParent()) {
- cont = false;
- break;
- }
- }
- }
- break;
- }
- case PRECEDING_SIBLING_AXIS:
- {
- nodes->setReverse();
- while (walker.moveToPreviousSibling()) {
- if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
- nodes->append(walker.getCurrentPosition());
- }
- }
- break;
- }
- case SELF_AXIS:
- {
- if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
- nodes->append(walker.getCurrentPosition());
- }
- break;
- }
- default: // Children Axis
- {
- if (!walker.moveToFirstChild()) {
- break;
- }
- do {
- if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
- nodes->append(walker.getCurrentPosition());
- }
- } while (walker.moveToNextSibling());
- break;
- }
- }
- // Apply predicates
- if (!isEmpty()) {
- rv = evaluatePredicates(nodes, aContext);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- nodes->unsetReverse();
- NS_ADDREF(*aResult = nodes);
- return NS_OK;
- }
- void LocationStep::fromDescendants(const txXPathNode& aNode,
- txIMatchContext* aCs,
- txNodeSet* aNodes)
- {
- txXPathTreeWalker walker(aNode);
- if (!walker.moveToFirstChild()) {
- return;
- }
- do {
- const txXPathNode& child = walker.getCurrentPosition();
- if (mNodeTest->matches(child, aCs)) {
- aNodes->append(child);
- }
- fromDescendants(child, aCs, aNodes);
- } while (walker.moveToNextSibling());
- }
- void LocationStep::fromDescendantsRev(const txXPathNode& aNode,
- txIMatchContext* aCs,
- txNodeSet* aNodes)
- {
- txXPathTreeWalker walker(aNode);
- if (!walker.moveToLastChild()) {
- return;
- }
- do {
- const txXPathNode& child = walker.getCurrentPosition();
- fromDescendantsRev(child, aCs, aNodes);
- if (mNodeTest->matches(child, aCs)) {
- aNodes->append(child);
- }
- } while (walker.moveToPreviousSibling());
- }
- Expr::ExprType
- LocationStep::getType()
- {
- return LOCATIONSTEP_EXPR;
- }
- TX_IMPL_EXPR_STUBS_BASE(LocationStep, NODESET_RESULT)
- Expr*
- LocationStep::getSubExprAt(uint32_t aPos)
- {
- return PredicateList::getSubExprAt(aPos);
- }
- void
- LocationStep::setSubExprAt(uint32_t aPos, Expr* aExpr)
- {
- PredicateList::setSubExprAt(aPos, aExpr);
- }
- bool
- LocationStep::isSensitiveTo(ContextSensitivity aContext)
- {
- return (aContext & NODE_CONTEXT) ||
- mNodeTest->isSensitiveTo(aContext) ||
- PredicateList::isSensitiveTo(aContext);
- }
- #ifdef TX_TO_STRING
- void
- LocationStep::toString(nsAString& str)
- {
- switch (mAxisIdentifier) {
- case ANCESTOR_AXIS :
- str.AppendLiteral("ancestor::");
- break;
- case ANCESTOR_OR_SELF_AXIS :
- str.AppendLiteral("ancestor-or-self::");
- break;
- case ATTRIBUTE_AXIS:
- str.Append(char16_t('@'));
- break;
- case DESCENDANT_AXIS:
- str.AppendLiteral("descendant::");
- break;
- case DESCENDANT_OR_SELF_AXIS:
- str.AppendLiteral("descendant-or-self::");
- break;
- case FOLLOWING_AXIS :
- str.AppendLiteral("following::");
- break;
- case FOLLOWING_SIBLING_AXIS:
- str.AppendLiteral("following-sibling::");
- break;
- case NAMESPACE_AXIS:
- str.AppendLiteral("namespace::");
- break;
- case PARENT_AXIS :
- str.AppendLiteral("parent::");
- break;
- case PRECEDING_AXIS :
- str.AppendLiteral("preceding::");
- break;
- case PRECEDING_SIBLING_AXIS :
- str.AppendLiteral("preceding-sibling::");
- break;
- case SELF_AXIS :
- str.AppendLiteral("self::");
- break;
- default:
- break;
- }
- NS_ASSERTION(mNodeTest, "mNodeTest is null, that's verboten");
- mNodeTest->toString(str);
- PredicateList::toString(str);
- }
- #endif
|