tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

txLocationStep.cpp (8104B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      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 /*
      7  Implementation of an XPath LocationStep
      8 */
      9 
     10 #include "txExpr.h"
     11 #include "txIXPathContext.h"
     12 #include "txNodeSet.h"
     13 #include "txXPathTreeWalker.h"
     14 
     15 //-----------------------------/
     16 //- Virtual methods from Expr -/
     17 //-----------------------------/
     18 
     19 /**
     20 * Evaluates this Expr based on the given context node and processor state
     21 * @param context the context node for evaluation of this Expr
     22 * @param ps the ProcessorState containing the stack information needed
     23 * for evaluation
     24 * @return the result of the evaluation
     25 * @see Expr
     26 **/
     27 nsresult LocationStep::evaluate(txIEvalContext* aContext,
     28                                txAExprResult** aResult) {
     29  NS_ASSERTION(aContext, "internal error");
     30  *aResult = nullptr;
     31 
     32  RefPtr<txNodeSet> nodes;
     33  nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes));
     34  NS_ENSURE_SUCCESS(rv, rv);
     35 
     36  txXPathTreeWalker walker(aContext->getContextNode());
     37 
     38  switch (mAxisIdentifier) {
     39    case ANCESTOR_AXIS: {
     40      if (!walker.moveToParent()) {
     41        break;
     42      }
     43      [[fallthrough]];
     44    }
     45    case ANCESTOR_OR_SELF_AXIS: {
     46      nodes->setReverse();
     47 
     48      do {
     49        rv = appendIfMatching(walker, aContext, nodes);
     50        NS_ENSURE_SUCCESS(rv, rv);
     51      } while (walker.moveToParent());
     52 
     53      break;
     54    }
     55    case ATTRIBUTE_AXIS: {
     56      if (!walker.moveToFirstAttribute()) {
     57        break;
     58      }
     59 
     60      do {
     61        rv = appendIfMatching(walker, aContext, nodes);
     62        NS_ENSURE_SUCCESS(rv, rv);
     63      } while (walker.moveToNextAttribute());
     64      break;
     65    }
     66    case DESCENDANT_OR_SELF_AXIS: {
     67      rv = appendIfMatching(walker, aContext, nodes);
     68      NS_ENSURE_SUCCESS(rv, rv);
     69      [[fallthrough]];
     70    }
     71    case DESCENDANT_AXIS: {
     72      rv = appendMatchingDescendants(walker, aContext, nodes);
     73      NS_ENSURE_SUCCESS(rv, rv);
     74      break;
     75    }
     76    case FOLLOWING_AXIS: {
     77      if (txXPathNodeUtils::isAttribute(walker.getCurrentPosition())) {
     78        walker.moveToParent();
     79        rv = appendMatchingDescendants(walker, aContext, nodes);
     80        NS_ENSURE_SUCCESS(rv, rv);
     81      }
     82      bool cont = true;
     83      while (!walker.moveToNextSibling()) {
     84        if (!walker.moveToParent()) {
     85          cont = false;
     86          break;
     87        }
     88      }
     89      while (cont) {
     90        rv = appendIfMatching(walker, aContext, nodes);
     91        NS_ENSURE_SUCCESS(rv, rv);
     92 
     93        rv = appendMatchingDescendants(walker, aContext, nodes);
     94        NS_ENSURE_SUCCESS(rv, rv);
     95 
     96        while (!walker.moveToNextSibling()) {
     97          if (!walker.moveToParent()) {
     98            cont = false;
     99            break;
    100          }
    101        }
    102      }
    103      break;
    104    }
    105    case FOLLOWING_SIBLING_AXIS: {
    106      while (walker.moveToNextSibling()) {
    107        rv = appendIfMatching(walker, aContext, nodes);
    108        NS_ENSURE_SUCCESS(rv, rv);
    109      }
    110      break;
    111    }
    112    case NAMESPACE_AXIS:  //-- not yet implemented
    113 #if 0
    114            // XXX DEBUG OUTPUT
    115            cout << "namespace axis not yet implemented"<<endl;
    116 #endif
    117      break;
    118    case PARENT_AXIS: {
    119      if (walker.moveToParent()) {
    120        rv = appendIfMatching(walker, aContext, nodes);
    121        NS_ENSURE_SUCCESS(rv, rv);
    122      }
    123      break;
    124    }
    125    case PRECEDING_AXIS: {
    126      nodes->setReverse();
    127 
    128      bool cont = true;
    129      while (!walker.moveToPreviousSibling()) {
    130        if (!walker.moveToParent()) {
    131          cont = false;
    132          break;
    133        }
    134      }
    135      while (cont) {
    136        rv = appendMatchingDescendantsRev(walker, aContext, nodes);
    137        NS_ENSURE_SUCCESS(rv, rv);
    138 
    139        rv = appendIfMatching(walker, aContext, nodes);
    140        NS_ENSURE_SUCCESS(rv, rv);
    141 
    142        while (!walker.moveToPreviousSibling()) {
    143          if (!walker.moveToParent()) {
    144            cont = false;
    145            break;
    146          }
    147        }
    148      }
    149      break;
    150    }
    151    case PRECEDING_SIBLING_AXIS: {
    152      nodes->setReverse();
    153 
    154      while (walker.moveToPreviousSibling()) {
    155        rv = appendIfMatching(walker, aContext, nodes);
    156        NS_ENSURE_SUCCESS(rv, rv);
    157      }
    158      break;
    159    }
    160    case SELF_AXIS: {
    161      rv = appendIfMatching(walker, aContext, nodes);
    162      NS_ENSURE_SUCCESS(rv, rv);
    163      break;
    164    }
    165    default:  // Children Axis
    166    {
    167      if (!walker.moveToFirstChild()) {
    168        break;
    169      }
    170 
    171      do {
    172        rv = appendIfMatching(walker, aContext, nodes);
    173        NS_ENSURE_SUCCESS(rv, rv);
    174      } while (walker.moveToNextSibling());
    175      break;
    176    }
    177  }
    178 
    179  // Apply predicates
    180  if (!isEmpty()) {
    181    rv = evaluatePredicates(nodes, aContext);
    182    NS_ENSURE_SUCCESS(rv, rv);
    183  }
    184 
    185  nodes->unsetReverse();
    186 
    187  NS_ADDREF(*aResult = nodes);
    188 
    189  return NS_OK;
    190 }
    191 
    192 nsresult LocationStep::appendIfMatching(const txXPathTreeWalker& aWalker,
    193                                        txIMatchContext* aContext,
    194                                        txNodeSet* aNodes) {
    195  bool matched;
    196  const txXPathNode& child = aWalker.getCurrentPosition();
    197  nsresult rv = mNodeTest->matches(child, aContext, matched);
    198  NS_ENSURE_SUCCESS(rv, rv);
    199 
    200  if (matched) {
    201    aNodes->append(child);
    202  }
    203  return NS_OK;
    204 }
    205 
    206 nsresult LocationStep::appendMatchingDescendants(
    207    const txXPathTreeWalker& aWalker, txIMatchContext* aContext,
    208    txNodeSet* aNodes) {
    209  txXPathTreeWalker walker(aWalker);
    210  if (!walker.moveToFirstChild()) {
    211    return NS_OK;
    212  }
    213 
    214  do {
    215    nsresult rv = appendIfMatching(walker, aContext, aNodes);
    216    NS_ENSURE_SUCCESS(rv, rv);
    217 
    218    rv = appendMatchingDescendants(walker, aContext, aNodes);
    219    NS_ENSURE_SUCCESS(rv, rv);
    220  } while (walker.moveToNextSibling());
    221 
    222  return NS_OK;
    223 }
    224 
    225 nsresult LocationStep::appendMatchingDescendantsRev(
    226    const txXPathTreeWalker& aWalker, txIMatchContext* aContext,
    227    txNodeSet* aNodes) {
    228  txXPathTreeWalker walker(aWalker);
    229  if (!walker.moveToLastChild()) {
    230    return NS_OK;
    231  }
    232 
    233  do {
    234    nsresult rv = appendMatchingDescendantsRev(walker, aContext, aNodes);
    235    NS_ENSURE_SUCCESS(rv, rv);
    236 
    237    rv = appendIfMatching(walker, aContext, aNodes);
    238    NS_ENSURE_SUCCESS(rv, rv);
    239  } while (walker.moveToPreviousSibling());
    240 
    241  return NS_OK;
    242 }
    243 
    244 Expr::ExprType LocationStep::getType() { return LOCATIONSTEP_EXPR; }
    245 
    246 TX_IMPL_EXPR_STUBS_BASE(LocationStep, NODESET_RESULT)
    247 
    248 Expr* LocationStep::getSubExprAt(uint32_t aPos) {
    249  return PredicateList::getSubExprAt(aPos);
    250 }
    251 
    252 void LocationStep::setSubExprAt(uint32_t aPos, Expr* aExpr) {
    253  PredicateList::setSubExprAt(aPos, aExpr);
    254 }
    255 
    256 bool LocationStep::isSensitiveTo(ContextSensitivity aContext) {
    257  return (aContext & NODE_CONTEXT) || mNodeTest->isSensitiveTo(aContext) ||
    258         PredicateList::isSensitiveTo(aContext);
    259 }
    260 
    261 #ifdef TX_TO_STRING
    262 void LocationStep::toString(nsAString& str) {
    263  switch (mAxisIdentifier) {
    264    case ANCESTOR_AXIS:
    265      str.AppendLiteral("ancestor::");
    266      break;
    267    case ANCESTOR_OR_SELF_AXIS:
    268      str.AppendLiteral("ancestor-or-self::");
    269      break;
    270    case ATTRIBUTE_AXIS:
    271      str.Append(char16_t('@'));
    272      break;
    273    case DESCENDANT_AXIS:
    274      str.AppendLiteral("descendant::");
    275      break;
    276    case DESCENDANT_OR_SELF_AXIS:
    277      str.AppendLiteral("descendant-or-self::");
    278      break;
    279    case FOLLOWING_AXIS:
    280      str.AppendLiteral("following::");
    281      break;
    282    case FOLLOWING_SIBLING_AXIS:
    283      str.AppendLiteral("following-sibling::");
    284      break;
    285    case NAMESPACE_AXIS:
    286      str.AppendLiteral("namespace::");
    287      break;
    288    case PARENT_AXIS:
    289      str.AppendLiteral("parent::");
    290      break;
    291    case PRECEDING_AXIS:
    292      str.AppendLiteral("preceding::");
    293      break;
    294    case PRECEDING_SIBLING_AXIS:
    295      str.AppendLiteral("preceding-sibling::");
    296      break;
    297    case SELF_AXIS:
    298      str.AppendLiteral("self::");
    299      break;
    300    default:
    301      break;
    302  }
    303  NS_ASSERTION(mNodeTest, "mNodeTest is null, that's verboten");
    304  mNodeTest->toString(str);
    305 
    306  PredicateList::toString(str);
    307 }
    308 #endif