dom/xslt/xpath/txRelationalExpr.cpp

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:4670a86f1fd7
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/. */
5
6 #include "txExpr.h"
7 #include "txNodeSet.h"
8 #include "txIXPathContext.h"
9 #include "txXPathTreeWalker.h"
10
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;
21
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 }
28
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);
33
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 }
43
44 return false;
45 }
46
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 }
53
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);
58
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 }
68
69 return false;
70 }
71
72 // Neither is a NodeSet
73 if (mOp == EQUAL || mOp == NOT_EQUAL) {
74 bool result;
75 const nsString *lString, *rString;
76
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 }
82
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 }
90
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 }
114
115 return mOp == EQUAL ? result : !result;
116 }
117
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 }
142
143 return false;
144 }
145
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);
153
154 nsRefPtr<txAExprResult> rResult;
155 rv = mRightExpr->evaluate(aContext, getter_AddRefs(rResult));
156 NS_ENSURE_SUCCESS(rv, rv);
157
158 aContext->recycler()->
159 getBoolResult(compareResults(aContext, lResult, rResult), aResult);
160
161 return NS_OK;
162 }
163
164 TX_IMPL_EXPR_STUBS_2(RelationalExpr, BOOLEAN_RESULT, mLeftExpr, mRightExpr)
165
166 bool
167 RelationalExpr::isSensitiveTo(ContextSensitivity aContext)
168 {
169 return mLeftExpr->isSensitiveTo(aContext) ||
170 mRightExpr->isSensitiveTo(aContext);
171 }
172
173 #ifdef TX_TO_STRING
174 void
175 RelationalExpr::toString(nsAString& str)
176 {
177 mLeftExpr->toString(str);
178
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 }
199
200 mRightExpr->toString(str);
201 }
202 #endif

mercurial