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

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

mercurial