tor-browser

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

txRelationalExpr.cpp (5380B)


      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 #include "txExpr.h"
      7 #include "txIXPathContext.h"
      8 #include "txNodeSet.h"
      9 #include "txXPathTreeWalker.h"
     10 
     11 /**
     12 *  Compares the two ExprResults based on XPath 1.0 Recommendation (section 3.4)
     13 */
     14 bool RelationalExpr::compareResults(txIEvalContext* aContext,
     15                                    txAExprResult* aLeft,
     16                                    txAExprResult* aRight) {
     17  short ltype = aLeft->getResultType();
     18  short rtype = aRight->getResultType();
     19  nsresult rv = NS_OK;
     20 
     21  // Handle case for just Left NodeSet or Both NodeSets
     22  if (ltype == txAExprResult::NODESET) {
     23    if (rtype == txAExprResult::BOOLEAN) {
     24      BooleanResult leftBool(aLeft->booleanValue());
     25      return compareResults(aContext, &leftBool, aRight);
     26    }
     27 
     28    txNodeSet* nodeSet = static_cast<txNodeSet*>(aLeft);
     29    RefPtr<StringResult> strResult;
     30    rv = aContext->recycler()->getStringResult(getter_AddRefs(strResult));
     31    NS_ENSURE_SUCCESS(rv, false);
     32 
     33    int32_t i;
     34    for (i = 0; i < nodeSet->size(); ++i) {
     35      strResult->mValue.Truncate();
     36      txXPathNodeUtils::appendNodeValue(nodeSet->get(i), strResult->mValue);
     37      if (compareResults(aContext, strResult, aRight)) {
     38        return true;
     39      }
     40    }
     41 
     42    return false;
     43  }
     44 
     45  // Handle case for Just Right NodeSet
     46  if (rtype == txAExprResult::NODESET) {
     47    if (ltype == txAExprResult::BOOLEAN) {
     48      BooleanResult rightBool(aRight->booleanValue());
     49      return compareResults(aContext, aLeft, &rightBool);
     50    }
     51 
     52    txNodeSet* nodeSet = static_cast<txNodeSet*>(aRight);
     53    RefPtr<StringResult> strResult;
     54    rv = aContext->recycler()->getStringResult(getter_AddRefs(strResult));
     55    NS_ENSURE_SUCCESS(rv, false);
     56 
     57    int32_t i;
     58    for (i = 0; i < nodeSet->size(); ++i) {
     59      strResult->mValue.Truncate();
     60      txXPathNodeUtils::appendNodeValue(nodeSet->get(i), strResult->mValue);
     61      if (compareResults(aContext, aLeft, strResult)) {
     62        return true;
     63      }
     64    }
     65 
     66    return false;
     67  }
     68 
     69  // Neither is a NodeSet
     70  if (mOp == EQUAL || mOp == NOT_EQUAL) {
     71    bool result;
     72    const nsString *lString, *rString;
     73 
     74    // If either is a bool, compare as bools.
     75    if (ltype == txAExprResult::BOOLEAN || rtype == txAExprResult::BOOLEAN) {
     76      result = aLeft->booleanValue() == aRight->booleanValue();
     77    }
     78 
     79    // If either is a number, compare as numbers.
     80    else if (ltype == txAExprResult::NUMBER || rtype == txAExprResult::NUMBER) {
     81      double lval = aLeft->numberValue();
     82      double rval = aRight->numberValue();
     83      result = (lval == rval);
     84    }
     85 
     86    // Otherwise compare as strings. Try to use the stringobject in
     87    // StringResult if possible since that is a common case.
     88    else if ((lString = aLeft->stringValuePointer())) {
     89      if ((rString = aRight->stringValuePointer())) {
     90        result = lString->Equals(*rString);
     91      } else {
     92        nsAutoString rStr;
     93        aRight->stringValue(rStr);
     94        result = lString->Equals(rStr);
     95      }
     96    } else if ((rString = aRight->stringValuePointer())) {
     97      nsAutoString lStr;
     98      aLeft->stringValue(lStr);
     99      result = rString->Equals(lStr);
    100    } else {
    101      nsAutoString lStr, rStr;
    102      aLeft->stringValue(lStr);
    103      aRight->stringValue(rStr);
    104      result = lStr.Equals(rStr);
    105    }
    106 
    107    return mOp == EQUAL ? result : !result;
    108  }
    109 
    110  double leftDbl = aLeft->numberValue();
    111  double rightDbl = aRight->numberValue();
    112  switch (mOp) {
    113    case LESS_THAN: {
    114      return (leftDbl < rightDbl);
    115    }
    116    case LESS_OR_EQUAL: {
    117      return (leftDbl <= rightDbl);
    118    }
    119    case GREATER_THAN: {
    120      return (leftDbl > rightDbl);
    121    }
    122    case GREATER_OR_EQUAL: {
    123      return (leftDbl >= rightDbl);
    124    }
    125    default: {
    126      MOZ_ASSERT_UNREACHABLE("We should have caught all cases");
    127    }
    128  }
    129 
    130  return false;
    131 }
    132 
    133 nsresult RelationalExpr::evaluate(txIEvalContext* aContext,
    134                                  txAExprResult** aResult) {
    135  *aResult = nullptr;
    136  RefPtr<txAExprResult> lResult;
    137  nsresult rv = mLeftExpr->evaluate(aContext, getter_AddRefs(lResult));
    138  NS_ENSURE_SUCCESS(rv, rv);
    139 
    140  RefPtr<txAExprResult> rResult;
    141  rv = mRightExpr->evaluate(aContext, getter_AddRefs(rResult));
    142  NS_ENSURE_SUCCESS(rv, rv);
    143 
    144  aContext->recycler()->getBoolResult(
    145      compareResults(aContext, lResult, rResult), aResult);
    146 
    147  return NS_OK;
    148 }
    149 
    150 TX_IMPL_EXPR_STUBS_2(RelationalExpr, BOOLEAN_RESULT, mLeftExpr, mRightExpr)
    151 
    152 bool RelationalExpr::isSensitiveTo(ContextSensitivity aContext) {
    153  return mLeftExpr->isSensitiveTo(aContext) ||
    154         mRightExpr->isSensitiveTo(aContext);
    155 }
    156 
    157 #ifdef TX_TO_STRING
    158 void RelationalExpr::toString(nsAString& str) {
    159  mLeftExpr->toString(str);
    160 
    161  switch (mOp) {
    162    case NOT_EQUAL:
    163      str.AppendLiteral("!=");
    164      break;
    165    case LESS_THAN:
    166      str.Append(char16_t('<'));
    167      break;
    168    case LESS_OR_EQUAL:
    169      str.AppendLiteral("<=");
    170      break;
    171    case GREATER_THAN:
    172      str.Append(char16_t('>'));
    173      break;
    174    case GREATER_OR_EQUAL:
    175      str.AppendLiteral(">=");
    176      break;
    177    default:
    178      str.Append(char16_t('='));
    179      break;
    180  }
    181 
    182  mRightExpr->toString(str);
    183 }
    184 #endif