Bug 1874684 - Part 4: Prefer const references instead of copying Instant values....
[gecko.git] / dom / xslt / xpath / txRelationalExpr.cpp
blobdf6da87ca8df35c1ab8575b6383a9750c959b138
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/. */
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)
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;
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);
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);
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;
42 return false;
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);
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);
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;
66 return false;
69 // Neither is a NodeSet
70 if (mOp == EQUAL || mOp == NOT_EQUAL) {
71 bool result;
72 const nsString *lString, *rString;
74 // If either is a bool, compare as bools.
75 if (ltype == txAExprResult::BOOLEAN || rtype == txAExprResult::BOOLEAN) {
76 result = aLeft->booleanValue() == aRight->booleanValue();
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);
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);
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);
107 return mOp == EQUAL ? result : !result;
110 double leftDbl = aLeft->numberValue();
111 double rightDbl = aRight->numberValue();
112 switch (mOp) {
113 case LESS_THAN: {
114 return (leftDbl < rightDbl);
116 case LESS_OR_EQUAL: {
117 return (leftDbl <= rightDbl);
119 case GREATER_THAN: {
120 return (leftDbl > rightDbl);
122 case GREATER_OR_EQUAL: {
123 return (leftDbl >= rightDbl);
125 default: {
126 MOZ_ASSERT_UNREACHABLE("We should have caught all cases");
130 return false;
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);
140 RefPtr<txAExprResult> rResult;
141 rv = mRightExpr->evaluate(aContext, getter_AddRefs(rResult));
142 NS_ENSURE_SUCCESS(rv, rv);
144 aContext->recycler()->getBoolResult(
145 compareResults(aContext, lResult, rResult), aResult);
147 return NS_OK;
150 TX_IMPL_EXPR_STUBS_2(RelationalExpr, BOOLEAN_RESULT, mLeftExpr, mRightExpr)
152 bool RelationalExpr::isSensitiveTo(ContextSensitivity aContext) {
153 return mLeftExpr->isSensitiveTo(aContext) ||
154 mRightExpr->isSensitiveTo(aContext);
157 #ifdef TX_TO_STRING
158 void RelationalExpr::toString(nsAString& str) {
159 mLeftExpr->toString(str);
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;
182 mRightExpr->toString(str);
184 #endif