LCOV - code coverage report
Current view: directory - content/xslt/src/xpath - txCoreFunctionCall.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 327 0 0.0 %
Date: 2012-06-02 Functions: 5 0 0.0 %

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

Generated by: LCOV version 1.7