1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/xslt/xpath/txRelationalExpr.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,202 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "txExpr.h" 1.10 +#include "txNodeSet.h" 1.11 +#include "txIXPathContext.h" 1.12 +#include "txXPathTreeWalker.h" 1.13 + 1.14 +/** 1.15 + * Compares the two ExprResults based on XPath 1.0 Recommendation (section 3.4) 1.16 + */ 1.17 +bool 1.18 +RelationalExpr::compareResults(txIEvalContext* aContext, txAExprResult* aLeft, 1.19 + txAExprResult* aRight) 1.20 +{ 1.21 + short ltype = aLeft->getResultType(); 1.22 + short rtype = aRight->getResultType(); 1.23 + nsresult rv = NS_OK; 1.24 + 1.25 + // Handle case for just Left NodeSet or Both NodeSets 1.26 + if (ltype == txAExprResult::NODESET) { 1.27 + if (rtype == txAExprResult::BOOLEAN) { 1.28 + BooleanResult leftBool(aLeft->booleanValue()); 1.29 + return compareResults(aContext, &leftBool, aRight); 1.30 + } 1.31 + 1.32 + txNodeSet* nodeSet = static_cast<txNodeSet*>(aLeft); 1.33 + nsRefPtr<StringResult> strResult; 1.34 + rv = aContext->recycler()->getStringResult(getter_AddRefs(strResult)); 1.35 + NS_ENSURE_SUCCESS(rv, false); 1.36 + 1.37 + int32_t i; 1.38 + for (i = 0; i < nodeSet->size(); ++i) { 1.39 + strResult->mValue.Truncate(); 1.40 + txXPathNodeUtils::appendNodeValue(nodeSet->get(i), 1.41 + strResult->mValue); 1.42 + if (compareResults(aContext, strResult, aRight)) { 1.43 + return true; 1.44 + } 1.45 + } 1.46 + 1.47 + return false; 1.48 + } 1.49 + 1.50 + // Handle case for Just Right NodeSet 1.51 + if (rtype == txAExprResult::NODESET) { 1.52 + if (ltype == txAExprResult::BOOLEAN) { 1.53 + BooleanResult rightBool(aRight->booleanValue()); 1.54 + return compareResults(aContext, aLeft, &rightBool); 1.55 + } 1.56 + 1.57 + txNodeSet* nodeSet = static_cast<txNodeSet*>(aRight); 1.58 + nsRefPtr<StringResult> strResult; 1.59 + rv = aContext->recycler()->getStringResult(getter_AddRefs(strResult)); 1.60 + NS_ENSURE_SUCCESS(rv, false); 1.61 + 1.62 + int32_t i; 1.63 + for (i = 0; i < nodeSet->size(); ++i) { 1.64 + strResult->mValue.Truncate(); 1.65 + txXPathNodeUtils::appendNodeValue(nodeSet->get(i), 1.66 + strResult->mValue); 1.67 + if (compareResults(aContext, aLeft, strResult)) { 1.68 + return true; 1.69 + } 1.70 + } 1.71 + 1.72 + return false; 1.73 + } 1.74 + 1.75 + // Neither is a NodeSet 1.76 + if (mOp == EQUAL || mOp == NOT_EQUAL) { 1.77 + bool result; 1.78 + const nsString *lString, *rString; 1.79 + 1.80 + // If either is a bool, compare as bools. 1.81 + if (ltype == txAExprResult::BOOLEAN || 1.82 + rtype == txAExprResult::BOOLEAN) { 1.83 + result = aLeft->booleanValue() == aRight->booleanValue(); 1.84 + } 1.85 + 1.86 + // If either is a number, compare as numbers. 1.87 + else if (ltype == txAExprResult::NUMBER || 1.88 + rtype == txAExprResult::NUMBER) { 1.89 + double lval = aLeft->numberValue(); 1.90 + double rval = aRight->numberValue(); 1.91 + result = (lval == rval); 1.92 + } 1.93 + 1.94 + // Otherwise compare as strings. Try to use the stringobject in 1.95 + // StringResult if possible since that is a common case. 1.96 + else if ((lString = aLeft->stringValuePointer())) { 1.97 + if ((rString = aRight->stringValuePointer())) { 1.98 + result = lString->Equals(*rString); 1.99 + } 1.100 + else { 1.101 + nsAutoString rStr; 1.102 + aRight->stringValue(rStr); 1.103 + result = lString->Equals(rStr); 1.104 + } 1.105 + } 1.106 + else if ((rString = aRight->stringValuePointer())) { 1.107 + nsAutoString lStr; 1.108 + aLeft->stringValue(lStr); 1.109 + result = rString->Equals(lStr); 1.110 + } 1.111 + else { 1.112 + nsAutoString lStr, rStr; 1.113 + aLeft->stringValue(lStr); 1.114 + aRight->stringValue(rStr); 1.115 + result = lStr.Equals(rStr); 1.116 + } 1.117 + 1.118 + return mOp == EQUAL ? result : !result; 1.119 + } 1.120 + 1.121 + double leftDbl = aLeft->numberValue(); 1.122 + double rightDbl = aRight->numberValue(); 1.123 + switch (mOp) { 1.124 + case LESS_THAN: 1.125 + { 1.126 + return (leftDbl < rightDbl); 1.127 + } 1.128 + case LESS_OR_EQUAL: 1.129 + { 1.130 + return (leftDbl <= rightDbl); 1.131 + } 1.132 + case GREATER_THAN: 1.133 + { 1.134 + return (leftDbl > rightDbl); 1.135 + } 1.136 + case GREATER_OR_EQUAL: 1.137 + { 1.138 + return (leftDbl >= rightDbl); 1.139 + } 1.140 + default: 1.141 + { 1.142 + NS_NOTREACHED("We should have caught all cases"); 1.143 + } 1.144 + } 1.145 + 1.146 + return false; 1.147 +} 1.148 + 1.149 +nsresult 1.150 +RelationalExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult) 1.151 +{ 1.152 + *aResult = nullptr; 1.153 + nsRefPtr<txAExprResult> lResult; 1.154 + nsresult rv = mLeftExpr->evaluate(aContext, getter_AddRefs(lResult)); 1.155 + NS_ENSURE_SUCCESS(rv, rv); 1.156 + 1.157 + nsRefPtr<txAExprResult> rResult; 1.158 + rv = mRightExpr->evaluate(aContext, getter_AddRefs(rResult)); 1.159 + NS_ENSURE_SUCCESS(rv, rv); 1.160 + 1.161 + aContext->recycler()-> 1.162 + getBoolResult(compareResults(aContext, lResult, rResult), aResult); 1.163 + 1.164 + return NS_OK; 1.165 +} 1.166 + 1.167 +TX_IMPL_EXPR_STUBS_2(RelationalExpr, BOOLEAN_RESULT, mLeftExpr, mRightExpr) 1.168 + 1.169 +bool 1.170 +RelationalExpr::isSensitiveTo(ContextSensitivity aContext) 1.171 +{ 1.172 + return mLeftExpr->isSensitiveTo(aContext) || 1.173 + mRightExpr->isSensitiveTo(aContext); 1.174 +} 1.175 + 1.176 +#ifdef TX_TO_STRING 1.177 +void 1.178 +RelationalExpr::toString(nsAString& str) 1.179 +{ 1.180 + mLeftExpr->toString(str); 1.181 + 1.182 + switch (mOp) { 1.183 + case NOT_EQUAL: 1.184 + str.AppendLiteral("!="); 1.185 + break; 1.186 + case LESS_THAN: 1.187 + str.Append(char16_t('<')); 1.188 + break; 1.189 + case LESS_OR_EQUAL: 1.190 + str.AppendLiteral("<="); 1.191 + break; 1.192 + case GREATER_THAN : 1.193 + str.Append(char16_t('>')); 1.194 + break; 1.195 + case GREATER_OR_EQUAL: 1.196 + str.AppendLiteral(">="); 1.197 + break; 1.198 + default: 1.199 + str.Append(char16_t('=')); 1.200 + break; 1.201 + } 1.202 + 1.203 + mRightExpr->toString(str); 1.204 +} 1.205 +#endif