LCOV - code coverage report
Current view: top level - dom/xslt/xpath - txPathExpr.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 120 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "txExpr.h"
       7             : #include "txNodeSet.h"
       8             : #include "txNodeSetContext.h"
       9             : #include "txSingleNodeContext.h"
      10             : #include "txXMLUtils.h"
      11             : #include "txXPathTreeWalker.h"
      12             : 
      13             :   //------------/
      14             :  //- PathExpr -/
      15             : //------------/
      16             : 
      17             : /**
      18             :  * Adds the Expr to this PathExpr
      19             :  * @param expr the Expr to add to this PathExpr
      20             : **/
      21             : nsresult
      22           0 : PathExpr::addExpr(Expr* aExpr, PathOperator aPathOp)
      23             : {
      24           0 :     NS_ASSERTION(!mItems.IsEmpty() || aPathOp == RELATIVE_OP,
      25             :                  "First step has to be relative in PathExpr");
      26           0 :     PathExprItem* pxi = mItems.AppendElement();
      27           0 :     if (!pxi) {
      28           0 :         return NS_ERROR_OUT_OF_MEMORY;
      29             :     }
      30           0 :     pxi->expr = aExpr;
      31           0 :     pxi->pathOp = aPathOp;
      32             : 
      33           0 :     return NS_OK;
      34             : }
      35             : 
      36             :     //-----------------------------/
      37             :   //- Virtual methods from Expr -/
      38             : //-----------------------------/
      39             : 
      40             : /**
      41             :  * Evaluates this Expr based on the given context node and processor state
      42             :  * @param context the context node for evaluation of this Expr
      43             :  * @param ps the ContextState containing the stack information needed
      44             :  * for evaluation
      45             :  * @return the result of the evaluation
      46             : **/
      47             : nsresult
      48           0 : PathExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
      49             : {
      50           0 :     *aResult = nullptr;
      51             : 
      52             :     // We need to evaluate the first step with the current context since it
      53             :     // can depend on the context size and position. For example:
      54             :     // key('books', concat('book', position()))
      55           0 :     RefPtr<txAExprResult> res;
      56           0 :     nsresult rv = mItems[0].expr->evaluate(aContext, getter_AddRefs(res));
      57           0 :     NS_ENSURE_SUCCESS(rv, rv);
      58             : 
      59           0 :     NS_ENSURE_TRUE(res->getResultType() == txAExprResult::NODESET,
      60             :                    NS_ERROR_XSLT_NODESET_EXPECTED);
      61             : 
      62             :     RefPtr<txNodeSet> nodes = static_cast<txNodeSet*>
      63           0 :                                            (static_cast<txAExprResult*>
      64           0 :                                                        (res));
      65           0 :     if (nodes->isEmpty()) {
      66           0 :         res.forget(aResult);
      67             : 
      68           0 :         return NS_OK;
      69             :     }
      70           0 :     res = nullptr; // To allow recycling
      71             : 
      72             :     // Evaluate remaining steps
      73           0 :     uint32_t i, len = mItems.Length();
      74           0 :     for (i = 1; i < len; ++i) {
      75           0 :         PathExprItem& pxi = mItems[i];
      76           0 :         RefPtr<txNodeSet> tmpNodes;
      77           0 :         txNodeSetContext eContext(nodes, aContext);
      78           0 :         while (eContext.hasNext()) {
      79           0 :             eContext.next();
      80             : 
      81           0 :             RefPtr<txNodeSet> resNodes;
      82           0 :             if (pxi.pathOp == DESCENDANT_OP) {
      83           0 :                 rv = aContext->recycler()->getNodeSet(getter_AddRefs(resNodes));
      84           0 :                 NS_ENSURE_SUCCESS(rv, rv);
      85             : 
      86           0 :                 rv = evalDescendants(pxi.expr, eContext.getContextNode(),
      87           0 :                                      &eContext, resNodes);
      88           0 :                 NS_ENSURE_SUCCESS(rv, rv);
      89             :             }
      90             :             else {
      91           0 :                 RefPtr<txAExprResult> res;
      92           0 :                 rv = pxi.expr->evaluate(&eContext, getter_AddRefs(res));
      93           0 :                 NS_ENSURE_SUCCESS(rv, rv);
      94             : 
      95           0 :                 if (res->getResultType() != txAExprResult::NODESET) {
      96             :                     //XXX ErrorReport: report nonnodeset error
      97           0 :                     return NS_ERROR_XSLT_NODESET_EXPECTED;
      98             :                 }
      99             :                 resNodes = static_cast<txNodeSet*>
     100           0 :                                       (static_cast<txAExprResult*>
     101           0 :                                                   (res));
     102             :             }
     103             : 
     104           0 :             if (tmpNodes) {
     105           0 :                 if (!resNodes->isEmpty()) {
     106           0 :                     RefPtr<txNodeSet> oldSet;
     107           0 :                     oldSet.swap(tmpNodes);
     108           0 :                     rv = aContext->recycler()->
     109           0 :                         getNonSharedNodeSet(oldSet, getter_AddRefs(tmpNodes));
     110           0 :                     NS_ENSURE_SUCCESS(rv, rv);
     111             : 
     112           0 :                     oldSet.swap(resNodes);
     113           0 :                     rv = aContext->recycler()->
     114           0 :                         getNonSharedNodeSet(oldSet, getter_AddRefs(resNodes));
     115           0 :                     NS_ENSURE_SUCCESS(rv, rv);
     116             : 
     117           0 :                     tmpNodes->addAndTransfer(resNodes);
     118             :                 }
     119             :             }
     120             :             else {
     121           0 :                 tmpNodes = resNodes;
     122             :             }
     123             :         }
     124           0 :         nodes = tmpNodes;
     125           0 :         if (nodes->isEmpty()) {
     126           0 :             break;
     127             :         }
     128             :     }
     129             : 
     130           0 :     *aResult = nodes;
     131           0 :     NS_ADDREF(*aResult);
     132             : 
     133           0 :     return NS_OK;
     134             : } //-- evaluate
     135             : 
     136             : /**
     137             :  * Selects from the descendants of the context node
     138             :  * all nodes that match the Expr
     139             : **/
     140             : nsresult
     141           0 : PathExpr::evalDescendants(Expr* aStep, const txXPathNode& aNode,
     142             :                           txIMatchContext* aContext, txNodeSet* resNodes)
     143             : {
     144           0 :     txSingleNodeContext eContext(aNode, aContext);
     145           0 :     RefPtr<txAExprResult> res;
     146           0 :     nsresult rv = aStep->evaluate(&eContext, getter_AddRefs(res));
     147           0 :     NS_ENSURE_SUCCESS(rv, rv);
     148             : 
     149           0 :     if (res->getResultType() != txAExprResult::NODESET) {
     150             :         //XXX ErrorReport: report nonnodeset error
     151           0 :         return NS_ERROR_XSLT_NODESET_EXPECTED;
     152             :     }
     153             : 
     154             :     txNodeSet* oldSet = static_cast<txNodeSet*>
     155           0 :                                    (static_cast<txAExprResult*>(res));
     156           0 :     RefPtr<txNodeSet> newSet;
     157           0 :     rv = aContext->recycler()->getNonSharedNodeSet(oldSet,
     158           0 :                                                    getter_AddRefs(newSet));
     159           0 :     NS_ENSURE_SUCCESS(rv, rv);
     160             : 
     161           0 :     resNodes->addAndTransfer(newSet);
     162             : 
     163             :     bool filterWS;
     164           0 :     rv = aContext->isStripSpaceAllowed(aNode, filterWS);
     165           0 :     NS_ENSURE_SUCCESS(rv, rv);
     166             : 
     167           0 :     txXPathTreeWalker walker(aNode);
     168           0 :     if (!walker.moveToFirstChild()) {
     169           0 :         return NS_OK;
     170             :     }
     171             : 
     172           0 :     do {
     173           0 :         const txXPathNode& node = walker.getCurrentPosition();
     174           0 :         if (!(filterWS && txXPathNodeUtils::isText(node) &&
     175           0 :               txXPathNodeUtils::isWhitespace(node))) {
     176           0 :             rv = evalDescendants(aStep, node, aContext, resNodes);
     177           0 :             NS_ENSURE_SUCCESS(rv, rv);
     178             :         }
     179             :     } while (walker.moveToNextSibling());
     180             : 
     181           0 :     return NS_OK;
     182             : } //-- evalDescendants
     183             : 
     184             : Expr::ExprType
     185           0 : PathExpr::getType()
     186             : {
     187           0 :   return PATH_EXPR;
     188             : }
     189             : 
     190           0 : TX_IMPL_EXPR_STUBS_BASE(PathExpr, NODESET_RESULT)
     191             : 
     192             : Expr*
     193           0 : PathExpr::getSubExprAt(uint32_t aPos)
     194             : {
     195           0 :     return aPos < mItems.Length() ? mItems[aPos].expr.get() : nullptr;
     196             : }
     197             : void
     198           0 : PathExpr::setSubExprAt(uint32_t aPos, Expr* aExpr)
     199             : {
     200           0 :     NS_ASSERTION(aPos < mItems.Length(), "setting bad subexpression index");
     201           0 :     mItems[aPos].expr.forget();
     202           0 :     mItems[aPos].expr = aExpr;
     203           0 : }
     204             : 
     205             : 
     206             : bool
     207           0 : PathExpr::isSensitiveTo(ContextSensitivity aContext)
     208             : {
     209           0 :     if (mItems[0].expr->isSensitiveTo(aContext)) {
     210           0 :         return true;
     211             :     }
     212             : 
     213             :     // We're creating a new node/nodeset so we can ignore those bits.
     214             :     Expr::ContextSensitivity context =
     215           0 :         aContext & ~(Expr::NODE_CONTEXT | Expr::NODESET_CONTEXT);
     216           0 :     if (context == NO_CONTEXT) {
     217           0 :         return false;
     218             :     }
     219             : 
     220           0 :     uint32_t i, len = mItems.Length();
     221           0 :     for (i = 0; i < len; ++i) {
     222           0 :         NS_ASSERTION(!mItems[i].expr->isSensitiveTo(Expr::NODESET_CONTEXT),
     223             :                      "Step cannot depend on nodeset-context");
     224           0 :         if (mItems[i].expr->isSensitiveTo(context)) {
     225           0 :             return true;
     226             :         }
     227             :     }
     228             : 
     229           0 :     return false;
     230             : }
     231             : 
     232             : #ifdef TX_TO_STRING
     233             : void
     234           0 : PathExpr::toString(nsAString& dest)
     235             : {
     236           0 :     if (!mItems.IsEmpty()) {
     237           0 :         NS_ASSERTION(mItems[0].pathOp == RELATIVE_OP,
     238             :                      "First step should be relative");
     239           0 :         mItems[0].expr->toString(dest);
     240             :     }
     241             : 
     242           0 :     uint32_t i, len = mItems.Length();
     243           0 :     for (i = 1; i < len; ++i) {
     244           0 :         switch (mItems[i].pathOp) {
     245             :             case DESCENDANT_OP:
     246           0 :                 dest.AppendLiteral("//");
     247           0 :                 break;
     248             :             case RELATIVE_OP:
     249           0 :                 dest.Append(char16_t('/'));
     250           0 :                 break;
     251             :         }
     252           0 :         mItems[i].expr->toString(dest);
     253             :     }
     254           0 : }
     255             : #endif

Generated by: LCOV version 1.13