LCOV - code coverage report
Current view: top level - dom/xslt/xpath - txCoreFunctionCall.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 331 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "mozilla/ArrayUtils.h"
       7             : #include "mozilla/FloatingPoint.h"
       8             : 
       9             : #include "txExpr.h"
      10             : #include "nsAutoPtr.h"
      11             : #include "txNodeSet.h"
      12             : #include "nsGkAtoms.h"
      13             : #include "txIXPathContext.h"
      14             : #include "nsWhitespaceTokenizer.h"
      15             : #include "txXPathTreeWalker.h"
      16             : #include <math.h>
      17             : #include "txStringUtils.h"
      18             : #include "txXMLUtils.h"
      19             : 
      20             : using namespace mozilla;
      21             : 
      22             : struct txCoreFunctionDescriptor
      23             : {
      24             :     int8_t mMinParams;
      25             :     int8_t mMaxParams;
      26             :     Expr::ResultType mReturnType;
      27             :     nsIAtom** mName;
      28             : };
      29             : 
      30             : // This must be ordered in the same order as txCoreFunctionCall::eType.
      31             : // If you change one, change the other.
      32             : static const txCoreFunctionDescriptor descriptTable[] =
      33             : {
      34             :     { 1, 1, Expr::NUMBER_RESULT,  &nsGkAtoms::count }, // COUNT
      35             :     { 1, 1, Expr::NODESET_RESULT, &nsGkAtoms::id }, // ID
      36             :     { 0, 0, Expr::NUMBER_RESULT,  &nsGkAtoms::last }, // LAST
      37             :     { 0, 1, Expr::STRING_RESULT,  &nsGkAtoms::localName }, // LOCAL_NAME
      38             :     { 0, 1, Expr::STRING_RESULT,  &nsGkAtoms::namespaceUri }, // NAMESPACE_URI
      39             :     { 0, 1, Expr::STRING_RESULT,  &nsGkAtoms::name }, // NAME
      40             :     { 0, 0, Expr::NUMBER_RESULT,  &nsGkAtoms::position }, // POSITION
      41             : 
      42             :     { 2, -1, Expr::STRING_RESULT, &nsGkAtoms::concat }, // CONCAT
      43             :     { 2, 2, Expr::BOOLEAN_RESULT, &nsGkAtoms::contains }, // CONTAINS
      44             :     { 0, 1, Expr::STRING_RESULT,  &nsGkAtoms::normalizeSpace }, // NORMALIZE_SPACE
      45             :     { 2, 2, Expr::BOOLEAN_RESULT, &nsGkAtoms::startsWith }, // STARTS_WITH
      46             :     { 0, 1, Expr::STRING_RESULT,  &nsGkAtoms::string }, // STRING
      47             :     { 0, 1, Expr::NUMBER_RESULT,  &nsGkAtoms::stringLength }, // STRING_LENGTH
      48             :     { 2, 3, Expr::STRING_RESULT,  &nsGkAtoms::substring }, // SUBSTRING
      49             :     { 2, 2, Expr::STRING_RESULT,  &nsGkAtoms::substringAfter }, // SUBSTRING_AFTER
      50             :     { 2, 2, Expr::STRING_RESULT,  &nsGkAtoms::substringBefore }, // SUBSTRING_BEFORE
      51             :     { 3, 3, Expr::STRING_RESULT,  &nsGkAtoms::translate }, // TRANSLATE
      52             : 
      53             :     { 0, 1, Expr::NUMBER_RESULT,  &nsGkAtoms::number }, // NUMBER
      54             :     { 1, 1, Expr::NUMBER_RESULT,  &nsGkAtoms::round }, // ROUND
      55             :     { 1, 1, Expr::NUMBER_RESULT,  &nsGkAtoms::floor }, // FLOOR
      56             :     { 1, 1, Expr::NUMBER_RESULT,  &nsGkAtoms::ceiling }, // CEILING
      57             :     { 1, 1, Expr::NUMBER_RESULT,  &nsGkAtoms::sum }, // SUM
      58             : 
      59             :     { 1, 1, Expr::BOOLEAN_RESULT, &nsGkAtoms::boolean }, // BOOLEAN
      60             :     { 0, 0, Expr::BOOLEAN_RESULT, &nsGkAtoms::_false }, // _FALSE
      61             :     { 1, 1, Expr::BOOLEAN_RESULT, &nsGkAtoms::lang }, // LANG
      62             :     { 1, 1, Expr::BOOLEAN_RESULT, &nsGkAtoms::_not }, // _NOT
      63             :     { 0, 0, Expr::BOOLEAN_RESULT, &nsGkAtoms::_true } // _TRUE
      64             : };
      65             : 
      66             : 
      67             : /*
      68             :  * Evaluates this Expr based on the given context node and processor state
      69             :  * @param context the context node for evaluation of this Expr
      70             :  * @param ps the ContextState containing the stack information needed
      71             :  * for evaluation
      72             :  * @return the result of the evaluation
      73             :  */
      74             : nsresult
      75           0 : txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
      76             : {
      77           0 :     *aResult = nullptr;
      78             : 
      79           0 :     if (!requireParams(descriptTable[mType].mMinParams,
      80           0 :                        descriptTable[mType].mMaxParams,
      81           0 :                        aContext)) {
      82           0 :         return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
      83             :     }
      84             : 
      85           0 :     nsresult rv = NS_OK;
      86           0 :     switch (mType) {
      87             :         case COUNT:
      88             :         {
      89           0 :             RefPtr<txNodeSet> nodes;
      90           0 :             rv = evaluateToNodeSet(mParams[0], aContext,
      91           0 :                                    getter_AddRefs(nodes));
      92           0 :             NS_ENSURE_SUCCESS(rv, rv);
      93             : 
      94           0 :             return aContext->recycler()->getNumberResult(nodes->size(),
      95           0 :                                                          aResult);
      96             :         }
      97             :         case ID:
      98             :         {
      99           0 :             RefPtr<txAExprResult> exprResult;
     100           0 :             rv = mParams[0]->evaluate(aContext, getter_AddRefs(exprResult));
     101           0 :             NS_ENSURE_SUCCESS(rv, rv);
     102             : 
     103           0 :             RefPtr<txNodeSet> resultSet;
     104           0 :             rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
     105           0 :             NS_ENSURE_SUCCESS(rv, rv);
     106             : 
     107           0 :             txXPathTreeWalker walker(aContext->getContextNode());
     108             : 
     109           0 :             if (exprResult->getResultType() == txAExprResult::NODESET) {
     110             :                 txNodeSet* nodes = static_cast<txNodeSet*>
     111             :                                               (static_cast<txAExprResult*>
     112           0 :                                                           (exprResult));
     113             :                 int32_t i;
     114           0 :                 for (i = 0; i < nodes->size(); ++i) {
     115           0 :                     nsAutoString idList;
     116           0 :                     txXPathNodeUtils::appendNodeValue(nodes->get(i), idList);
     117           0 :                     nsWhitespaceTokenizer tokenizer(idList);
     118           0 :                     while (tokenizer.hasMoreTokens()) {
     119           0 :                         if (walker.moveToElementById(tokenizer.nextToken())) {
     120           0 :                             resultSet->add(walker.getCurrentPosition());
     121             :                         }
     122             :                     }
     123             :                 }
     124             :             }
     125             :             else {
     126           0 :                 nsAutoString idList;
     127           0 :                 exprResult->stringValue(idList);
     128           0 :                 nsWhitespaceTokenizer tokenizer(idList);
     129           0 :                 while (tokenizer.hasMoreTokens()) {
     130           0 :                     if (walker.moveToElementById(tokenizer.nextToken())) {
     131           0 :                         resultSet->add(walker.getCurrentPosition());
     132             :                     }
     133             :                 }
     134             :             }
     135             : 
     136           0 :             *aResult = resultSet;
     137           0 :             NS_ADDREF(*aResult);
     138             : 
     139           0 :             return NS_OK;
     140             :         }
     141             :         case LAST:
     142             :         {
     143           0 :             return aContext->recycler()->getNumberResult(aContext->size(),
     144           0 :                                                          aResult);
     145             :         }
     146             :         case LOCAL_NAME:
     147             :         case NAME:
     148             :         case NAMESPACE_URI:
     149             :         {
     150             :             // Check for optional arg
     151           0 :             RefPtr<txNodeSet> nodes;
     152           0 :             if (!mParams.IsEmpty()) {
     153           0 :                 rv = evaluateToNodeSet(mParams[0], aContext,
     154           0 :                                        getter_AddRefs(nodes));
     155           0 :                 NS_ENSURE_SUCCESS(rv, rv);
     156             : 
     157           0 :                 if (nodes->isEmpty()) {
     158           0 :                     aContext->recycler()->getEmptyStringResult(aResult);
     159             : 
     160           0 :                     return NS_OK;
     161             :                 }
     162             :             }
     163             : 
     164           0 :             const txXPathNode& node = nodes ? nodes->get(0) :
     165           0 :                                               aContext->getContextNode();
     166           0 :             switch (mType) {
     167             :                 case LOCAL_NAME:
     168             :                 {
     169           0 :                     StringResult* strRes = nullptr;
     170           0 :                     rv = aContext->recycler()->getStringResult(&strRes);
     171           0 :                     NS_ENSURE_SUCCESS(rv, rv);
     172             : 
     173           0 :                     *aResult = strRes;
     174           0 :                     txXPathNodeUtils::getLocalName(node, strRes->mValue);
     175             : 
     176           0 :                     return NS_OK;
     177             :                 }
     178             :                 case NAMESPACE_URI:
     179             :                 {
     180           0 :                     StringResult* strRes = nullptr;
     181           0 :                     rv = aContext->recycler()->getStringResult(&strRes);
     182           0 :                     NS_ENSURE_SUCCESS(rv, rv);
     183             : 
     184           0 :                     *aResult = strRes;
     185           0 :                     txXPathNodeUtils::getNamespaceURI(node, strRes->mValue);
     186             : 
     187           0 :                     return NS_OK;
     188             :                 }
     189             :                 case NAME:
     190             :                 {
     191             :                     // XXX Namespace: namespaces have a name
     192           0 :                     if (txXPathNodeUtils::isAttribute(node) ||
     193           0 :                         txXPathNodeUtils::isElement(node) ||
     194           0 :                         txXPathNodeUtils::isProcessingInstruction(node)) {
     195           0 :                         StringResult* strRes = nullptr;
     196           0 :                         rv = aContext->recycler()->getStringResult(&strRes);
     197           0 :                         NS_ENSURE_SUCCESS(rv, rv);
     198             : 
     199           0 :                         *aResult = strRes;
     200           0 :                         txXPathNodeUtils::getNodeName(node, strRes->mValue);
     201             :                     }
     202             :                     else {
     203           0 :                         aContext->recycler()->getEmptyStringResult(aResult);
     204             :                     }
     205             : 
     206           0 :                     return NS_OK;
     207             :                 }
     208             :                 default:
     209             :                 {
     210           0 :                     MOZ_CRASH("Unexpected mType?!");
     211             :                 }
     212             :             }
     213             :             MOZ_CRASH("Inner mType switch should have returned!");
     214             :         }
     215             :         case POSITION:
     216             :         {
     217           0 :             return aContext->recycler()->getNumberResult(aContext->position(),
     218           0 :                                                          aResult);
     219             :         }
     220             : 
     221             :         // String functions
     222             : 
     223             :         case CONCAT:
     224             :         {
     225           0 :             RefPtr<StringResult> strRes;
     226           0 :             rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
     227           0 :             NS_ENSURE_SUCCESS(rv, rv);
     228             : 
     229           0 :             uint32_t i, len = mParams.Length();
     230           0 :             for (i = 0; i < len; ++i) {
     231           0 :                 rv = mParams[i]->evaluateToString(aContext, strRes->mValue);
     232           0 :                 NS_ENSURE_SUCCESS(rv, rv);
     233             :             }
     234             : 
     235           0 :             NS_ADDREF(*aResult = strRes);
     236             : 
     237           0 :             return NS_OK;
     238             :         }
     239             :         case CONTAINS:
     240             :         {
     241           0 :             nsAutoString arg2;
     242           0 :             rv = mParams[1]->evaluateToString(aContext, arg2);
     243           0 :             NS_ENSURE_SUCCESS(rv, rv);
     244             : 
     245           0 :             if (arg2.IsEmpty()) {
     246           0 :                 aContext->recycler()->getBoolResult(true, aResult);
     247             :             }
     248             :             else {
     249           0 :                 nsAutoString arg1;
     250           0 :                 rv = mParams[0]->evaluateToString(aContext, arg1);
     251           0 :                 NS_ENSURE_SUCCESS(rv, rv);
     252             : 
     253           0 :                 aContext->recycler()->getBoolResult(FindInReadable(arg2, arg1),
     254           0 :                                                     aResult);
     255             :             }
     256             : 
     257           0 :             return NS_OK;
     258             :         }
     259             :         case NORMALIZE_SPACE:
     260             :         {
     261           0 :             nsAutoString resultStr;
     262           0 :             if (!mParams.IsEmpty()) {
     263           0 :                 rv = mParams[0]->evaluateToString(aContext, resultStr);
     264           0 :                 NS_ENSURE_SUCCESS(rv, rv);
     265             :             }
     266             :             else {
     267           0 :                 txXPathNodeUtils::appendNodeValue(aContext->getContextNode(),
     268           0 :                                                   resultStr);
     269             :             }
     270             : 
     271           0 :             RefPtr<StringResult> strRes;
     272           0 :             rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
     273           0 :             NS_ENSURE_SUCCESS(rv, rv);
     274             : 
     275           0 :             bool addSpace = false;
     276           0 :             bool first = true;
     277           0 :             strRes->mValue.SetCapacity(resultStr.Length());
     278             :             char16_t c;
     279             :             uint32_t src;
     280           0 :             for (src = 0; src < resultStr.Length(); src++) {
     281           0 :                 c = resultStr.CharAt(src);
     282           0 :                 if (XMLUtils::isWhitespace(c)) {
     283           0 :                     addSpace = true;
     284             :                 }
     285             :                 else {
     286           0 :                     if (addSpace && !first)
     287           0 :                         strRes->mValue.Append(char16_t(' '));
     288             : 
     289           0 :                     strRes->mValue.Append(c);
     290           0 :                     addSpace = false;
     291           0 :                     first = false;
     292             :                 }
     293             :             }
     294           0 :             *aResult = strRes;
     295           0 :             NS_ADDREF(*aResult);
     296             : 
     297           0 :             return NS_OK;
     298             :         }
     299             :         case STARTS_WITH:
     300             :         {
     301           0 :             nsAutoString arg2;
     302           0 :             rv = mParams[1]->evaluateToString(aContext, arg2);
     303           0 :             NS_ENSURE_SUCCESS(rv, rv);
     304             : 
     305           0 :             bool result = false;
     306           0 :             if (arg2.IsEmpty()) {
     307           0 :                 result = true;
     308             :             }
     309             :             else {
     310           0 :                 nsAutoString arg1;
     311           0 :                 rv = mParams[0]->evaluateToString(aContext, arg1);
     312           0 :                 NS_ENSURE_SUCCESS(rv, rv);
     313             : 
     314           0 :                 result = StringBeginsWith(arg1, arg2);
     315             :             }
     316             : 
     317           0 :             aContext->recycler()->getBoolResult(result, aResult);
     318             : 
     319           0 :             return NS_OK;
     320             :         }
     321             :         case STRING:
     322             :         {
     323           0 :             RefPtr<StringResult> strRes;
     324           0 :             rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
     325           0 :             NS_ENSURE_SUCCESS(rv, rv);
     326             : 
     327           0 :             if (!mParams.IsEmpty()) {
     328           0 :                 rv = mParams[0]->evaluateToString(aContext, strRes->mValue);
     329           0 :                 NS_ENSURE_SUCCESS(rv, rv);
     330             :             }
     331             :             else {
     332           0 :                 txXPathNodeUtils::appendNodeValue(aContext->getContextNode(),
     333           0 :                                                   strRes->mValue);
     334             :             }
     335             : 
     336           0 :             NS_ADDREF(*aResult = strRes);
     337             : 
     338           0 :             return NS_OK;
     339             :         }
     340             :         case STRING_LENGTH:
     341             :         {
     342           0 :             nsAutoString resultStr;
     343           0 :             if (!mParams.IsEmpty()) {
     344           0 :                 rv = mParams[0]->evaluateToString(aContext, resultStr);
     345           0 :                 NS_ENSURE_SUCCESS(rv, rv);
     346             :             }
     347             :             else {
     348           0 :                 txXPathNodeUtils::appendNodeValue(aContext->getContextNode(),
     349           0 :                                                   resultStr);
     350             :             }
     351           0 :             rv = aContext->recycler()->getNumberResult(resultStr.Length(),
     352           0 :                                                        aResult);
     353           0 :             NS_ENSURE_SUCCESS(rv, rv);
     354             : 
     355           0 :             return NS_OK;
     356             :         }
     357             :         case SUBSTRING:
     358             :         {
     359           0 :             nsAutoString src;
     360           0 :             rv = mParams[0]->evaluateToString(aContext, src);
     361           0 :             NS_ENSURE_SUCCESS(rv, rv);
     362             : 
     363             :             double start;
     364           0 :             rv = evaluateToNumber(mParams[1], aContext, &start);
     365           0 :             NS_ENSURE_SUCCESS(rv, rv);
     366             : 
     367             :             // check for NaN or +/-Inf
     368           0 :             if (mozilla::IsNaN(start) ||
     369           0 :                 mozilla::IsInfinite(start) ||
     370           0 :                 start >= src.Length() + 0.5) {
     371           0 :                 aContext->recycler()->getEmptyStringResult(aResult);
     372             : 
     373           0 :                 return NS_OK;
     374             :             }
     375             : 
     376           0 :             start = floor(start + 0.5) - 1;
     377             : 
     378             :             double end;
     379           0 :             if (mParams.Length() == 3) {
     380           0 :                 rv = evaluateToNumber(mParams[2], aContext, &end);
     381           0 :                 NS_ENSURE_SUCCESS(rv, rv);
     382             : 
     383           0 :                 end += start;
     384           0 :                 if (mozilla::IsNaN(end) || end < 0) {
     385           0 :                     aContext->recycler()->getEmptyStringResult(aResult);
     386             : 
     387           0 :                     return NS_OK;
     388             :                 }
     389             : 
     390           0 :                 if (end > src.Length())
     391           0 :                     end = src.Length();
     392             :                 else
     393           0 :                     end = floor(end + 0.5);
     394             :             }
     395             :             else {
     396           0 :                 end = src.Length();
     397             :             }
     398             : 
     399           0 :             if (start < 0)
     400           0 :                 start = 0;
     401             : 
     402           0 :             if (start > end) {
     403           0 :                 aContext->recycler()->getEmptyStringResult(aResult);
     404             : 
     405           0 :                 return NS_OK;
     406             :             }
     407             : 
     408           0 :             return aContext->recycler()->getStringResult(
     409           0 :                   Substring(src, (uint32_t)start, (uint32_t)(end - start)),
     410           0 :                   aResult);
     411             :         }
     412             :         case SUBSTRING_AFTER:
     413             :         {
     414           0 :             nsAutoString arg1;
     415           0 :             rv = mParams[0]->evaluateToString(aContext, arg1);
     416           0 :             NS_ENSURE_SUCCESS(rv, rv);
     417             : 
     418           0 :             nsAutoString arg2;
     419           0 :             rv = mParams[1]->evaluateToString(aContext, arg2);
     420           0 :             NS_ENSURE_SUCCESS(rv, rv);
     421             : 
     422           0 :             if (arg2.IsEmpty()) {
     423           0 :                 return aContext->recycler()->getStringResult(arg1, aResult);
     424             :             }
     425             : 
     426           0 :             int32_t idx = arg1.Find(arg2);
     427           0 :             if (idx == kNotFound) {
     428           0 :                 aContext->recycler()->getEmptyStringResult(aResult);
     429             : 
     430           0 :                 return NS_OK;
     431             :             }
     432             : 
     433           0 :             const nsAString& result = Substring(arg1, idx + arg2.Length());
     434           0 :             return aContext->recycler()->getStringResult(result, aResult);
     435             :         }
     436             :         case SUBSTRING_BEFORE:
     437             :         {
     438           0 :             nsAutoString arg2;
     439           0 :             rv = mParams[1]->evaluateToString(aContext, arg2);
     440           0 :             NS_ENSURE_SUCCESS(rv, rv);
     441             : 
     442           0 :             if (arg2.IsEmpty()) {
     443           0 :                 aContext->recycler()->getEmptyStringResult(aResult);
     444             : 
     445           0 :                 return NS_OK;
     446             :             }
     447             : 
     448           0 :             nsAutoString arg1;
     449           0 :             rv = mParams[0]->evaluateToString(aContext, arg1);
     450           0 :             NS_ENSURE_SUCCESS(rv, rv);
     451             : 
     452           0 :             int32_t idx = arg1.Find(arg2);
     453           0 :             if (idx == kNotFound) {
     454           0 :                 aContext->recycler()->getEmptyStringResult(aResult);
     455             : 
     456           0 :                 return NS_OK;
     457             :             }
     458             : 
     459           0 :             return aContext->recycler()->getStringResult(StringHead(arg1, idx),
     460           0 :                                                          aResult);
     461             :         }
     462             :         case TRANSLATE:
     463             :         {
     464           0 :             nsAutoString src;
     465           0 :             rv = mParams[0]->evaluateToString(aContext, src);
     466           0 :             NS_ENSURE_SUCCESS(rv, rv);
     467             : 
     468           0 :             if (src.IsEmpty()) {
     469           0 :                 aContext->recycler()->getEmptyStringResult(aResult);
     470             : 
     471           0 :                 return NS_OK;
     472             :             }
     473             : 
     474           0 :             RefPtr<StringResult> strRes;
     475           0 :             rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
     476           0 :             NS_ENSURE_SUCCESS(rv, rv);
     477             : 
     478           0 :             strRes->mValue.SetCapacity(src.Length());
     479             : 
     480           0 :             nsAutoString oldChars, newChars;
     481           0 :             rv = mParams[1]->evaluateToString(aContext, oldChars);
     482           0 :             NS_ENSURE_SUCCESS(rv, rv);
     483             : 
     484           0 :             rv = mParams[2]->evaluateToString(aContext, newChars);
     485           0 :             NS_ENSURE_SUCCESS(rv, rv);
     486             : 
     487             :             uint32_t i;
     488           0 :             int32_t newCharsLength = (int32_t)newChars.Length();
     489           0 :             for (i = 0; i < src.Length(); i++) {
     490           0 :                 int32_t idx = oldChars.FindChar(src.CharAt(i));
     491           0 :                 if (idx != kNotFound) {
     492           0 :                     if (idx < newCharsLength)
     493           0 :                         strRes->mValue.Append(newChars.CharAt((uint32_t)idx));
     494             :                 }
     495             :                 else {
     496           0 :                     strRes->mValue.Append(src.CharAt(i));
     497             :                 }
     498             :             }
     499             : 
     500           0 :             NS_ADDREF(*aResult = strRes);
     501             : 
     502           0 :             return NS_OK;
     503             :         }
     504             : 
     505             :         // Number functions
     506             : 
     507             :         case NUMBER:
     508             :         {
     509             :             double res;
     510           0 :             if (!mParams.IsEmpty()) {
     511           0 :                 rv = evaluateToNumber(mParams[0], aContext, &res);
     512           0 :                 NS_ENSURE_SUCCESS(rv, rv);
     513             :             }
     514             :             else {
     515           0 :                 nsAutoString resultStr;
     516           0 :                 txXPathNodeUtils::appendNodeValue(aContext->getContextNode(),
     517           0 :                                                   resultStr);
     518           0 :                 res = txDouble::toDouble(resultStr);
     519             :             }
     520           0 :             return aContext->recycler()->getNumberResult(res, aResult);
     521             :         }
     522             :         case ROUND:
     523             :         {
     524             :             double dbl;
     525           0 :             rv = evaluateToNumber(mParams[0], aContext, &dbl);
     526           0 :             NS_ENSURE_SUCCESS(rv, rv);
     527             : 
     528           0 :             if (mozilla::IsFinite(dbl)) {
     529           0 :                 if (mozilla::IsNegative(dbl) && dbl >= -0.5) {
     530           0 :                     dbl *= 0;
     531             :                 }
     532             :                 else {
     533           0 :                     dbl = floor(dbl + 0.5);
     534             :                 }
     535             :             }
     536             : 
     537           0 :             return aContext->recycler()->getNumberResult(dbl, aResult);
     538             :         }
     539             :         case FLOOR:
     540             :         {
     541             :             double dbl;
     542           0 :             rv = evaluateToNumber(mParams[0], aContext, &dbl);
     543           0 :             NS_ENSURE_SUCCESS(rv, rv);
     544             : 
     545           0 :             if (mozilla::IsFinite(dbl) && !mozilla::IsNegativeZero(dbl))
     546           0 :                 dbl = floor(dbl);
     547             : 
     548           0 :             return aContext->recycler()->getNumberResult(dbl, aResult);
     549             :         }
     550             :         case CEILING:
     551             :         {
     552             :             double dbl;
     553           0 :             rv = evaluateToNumber(mParams[0], aContext, &dbl);
     554           0 :             NS_ENSURE_SUCCESS(rv, rv);
     555             : 
     556           0 :             if (mozilla::IsFinite(dbl)) {
     557           0 :                 if (mozilla::IsNegative(dbl) && dbl > -1)
     558           0 :                     dbl *= 0;
     559             :                 else
     560           0 :                     dbl = ceil(dbl);
     561             :             }
     562             : 
     563           0 :             return aContext->recycler()->getNumberResult(dbl, aResult);
     564             :         }
     565             :         case SUM:
     566             :         {
     567           0 :             RefPtr<txNodeSet> nodes;
     568           0 :             nsresult rv = evaluateToNodeSet(mParams[0], aContext,
     569           0 :                                             getter_AddRefs(nodes));
     570           0 :             NS_ENSURE_SUCCESS(rv, rv);
     571             : 
     572           0 :             double res = 0;
     573             :             int32_t i;
     574           0 :             for (i = 0; i < nodes->size(); ++i) {
     575           0 :                 nsAutoString resultStr;
     576           0 :                 txXPathNodeUtils::appendNodeValue(nodes->get(i), resultStr);
     577           0 :                 res += txDouble::toDouble(resultStr);
     578             :             }
     579           0 :             return aContext->recycler()->getNumberResult(res, aResult);
     580             :         }
     581             : 
     582             :         // Boolean functions
     583             : 
     584             :         case BOOLEAN:
     585             :         {
     586             :             bool result;
     587           0 :             nsresult rv = mParams[0]->evaluateToBool(aContext, result);
     588           0 :             NS_ENSURE_SUCCESS(rv, rv);
     589             : 
     590           0 :             aContext->recycler()->getBoolResult(result, aResult);
     591             : 
     592           0 :             return NS_OK;
     593             :         }
     594             :         case _FALSE:
     595             :         {
     596           0 :             aContext->recycler()->getBoolResult(false, aResult);
     597             : 
     598           0 :             return NS_OK;
     599             :         }
     600             :         case LANG:
     601             :         {
     602           0 :             txXPathTreeWalker walker(aContext->getContextNode());
     603             : 
     604           0 :             nsAutoString lang;
     605             :             bool found;
     606           0 :             do {
     607           0 :                 found = walker.getAttr(nsGkAtoms::lang, kNameSpaceID_XML,
     608           0 :                                        lang);
     609           0 :             } while (!found && walker.moveToParent());
     610             : 
     611           0 :             if (!found) {
     612           0 :                 aContext->recycler()->getBoolResult(false, aResult);
     613             : 
     614           0 :                 return NS_OK;
     615             :             }
     616             : 
     617           0 :             nsAutoString arg;
     618           0 :             rv = mParams[0]->evaluateToString(aContext, arg);
     619           0 :             NS_ENSURE_SUCCESS(rv, rv);
     620             : 
     621             :             bool result =
     622           0 :                 StringBeginsWith(lang, arg,
     623           0 :                                  txCaseInsensitiveStringComparator()) &&
     624           0 :                 (lang.Length() == arg.Length() ||
     625           0 :                  lang.CharAt(arg.Length()) == '-');
     626             : 
     627           0 :             aContext->recycler()->getBoolResult(result, aResult);
     628             : 
     629           0 :             return NS_OK;
     630             :         }
     631             :         case _NOT:
     632             :         {
     633             :             bool result;
     634           0 :             rv = mParams[0]->evaluateToBool(aContext, result);
     635           0 :             NS_ENSURE_SUCCESS(rv, rv);
     636             : 
     637           0 :             aContext->recycler()->getBoolResult(!result, aResult);
     638             : 
     639           0 :             return NS_OK;
     640             :         }
     641             :         case _TRUE:
     642             :         {
     643           0 :             aContext->recycler()->getBoolResult(true, aResult);
     644             : 
     645           0 :             return NS_OK;
     646             :         }
     647             :     }
     648             : 
     649           0 :     aContext->receiveError(NS_LITERAL_STRING("Internal error"),
     650           0 :                            NS_ERROR_UNEXPECTED);
     651           0 :     return NS_ERROR_UNEXPECTED;
     652             : }
     653             : 
     654             : Expr::ResultType
     655           0 : txCoreFunctionCall::getReturnType()
     656             : {
     657           0 :     return descriptTable[mType].mReturnType;
     658             : }
     659             : 
     660             : bool
     661           0 : txCoreFunctionCall::isSensitiveTo(ContextSensitivity aContext)
     662             : {
     663           0 :     switch (mType) {
     664             :         case COUNT:
     665             :         case CONCAT:
     666             :         case CONTAINS:
     667             :         case STARTS_WITH:
     668             :         case SUBSTRING:
     669             :         case SUBSTRING_AFTER:
     670             :         case SUBSTRING_BEFORE:
     671             :         case TRANSLATE:
     672             :         case ROUND:
     673             :         case FLOOR:
     674             :         case CEILING:
     675             :         case SUM:
     676             :         case BOOLEAN:
     677             :         case _NOT:
     678             :         case _FALSE:
     679             :         case _TRUE:
     680             :         {
     681           0 :             return argsSensitiveTo(aContext);
     682             :         }
     683             :         case ID:
     684             :         {
     685           0 :             return (aContext & NODE_CONTEXT) ||
     686           0 :                    argsSensitiveTo(aContext);
     687             :         }
     688             :         case LAST:
     689             :         {
     690           0 :             return !!(aContext & SIZE_CONTEXT);
     691             :         }
     692             :         case LOCAL_NAME:
     693             :         case NAME:
     694             :         case NAMESPACE_URI:
     695             :         case NORMALIZE_SPACE:
     696             :         case STRING:
     697             :         case STRING_LENGTH:
     698             :         case NUMBER:
     699             :         {
     700           0 :             if (mParams.IsEmpty()) {
     701           0 :                 return !!(aContext & NODE_CONTEXT);
     702             :             }
     703           0 :             return argsSensitiveTo(aContext);
     704             :         }
     705             :         case POSITION:
     706             :         {
     707           0 :             return !!(aContext & POSITION_CONTEXT);
     708             :         }
     709             :         case LANG:
     710             :         {
     711           0 :             return (aContext & NODE_CONTEXT) ||
     712           0 :                    argsSensitiveTo(aContext);
     713             :         }
     714             :     }
     715             : 
     716           0 :     NS_NOTREACHED("how'd we get here?");
     717           0 :     return true;
     718             : }
     719             : 
     720             : // static
     721             : bool
     722           0 : txCoreFunctionCall::getTypeFromAtom(nsIAtom* aName, eType& aType)
     723             : {
     724             :     uint32_t i;
     725           0 :     for (i = 0; i < ArrayLength(descriptTable); ++i) {
     726           0 :         if (aName == *descriptTable[i].mName) {
     727           0 :             aType = static_cast<eType>(i);
     728             : 
     729           0 :             return true;
     730             :         }
     731             :     }
     732             : 
     733           0 :     return false;
     734             : }
     735             : 
     736             : #ifdef TX_TO_STRING
     737             : nsresult
     738           0 : txCoreFunctionCall::getNameAtom(nsIAtom** aAtom)
     739             : {
     740           0 :     NS_ADDREF(*aAtom = *descriptTable[mType].mName);
     741           0 :     return NS_OK;
     742             : }
     743             : #endif

Generated by: LCOV version 1.13