dom/xslt/xpath/txRelationalExpr.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial