LCOV - code coverage report
Current view: directory - content/xslt/src/xslt - txEXSLTFunctions.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 345 7 2.0 %
Date: 2012-06-02 Functions: 13 1 7.7 %

       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 mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Peter Van der Beken.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2003
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Peter Van der Beken <peterv@propagandism.org>
      24                 :  *
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "mozilla/Util.h"
      41                 : 
      42                 : #include "nsIAtom.h"
      43                 : #include "nsGkAtoms.h"
      44                 : #include "txExecutionState.h"
      45                 : #include "txExpr.h"
      46                 : #include "txIXPathContext.h"
      47                 : #include "txNodeSet.h"
      48                 : #include "txOutputFormat.h"
      49                 : #include "txRtfHandler.h"
      50                 : #include "txXPathTreeWalker.h"
      51                 : #include "nsPrintfCString.h"
      52                 : #include "nsComponentManagerUtils.h"
      53                 : #include "nsContentCID.h"
      54                 : #include "nsContentCreatorFunctions.h"
      55                 : #include "nsIContent.h"
      56                 : #include "nsIDOMDocumentFragment.h"
      57                 : #include "txMozillaXMLOutput.h"
      58                 : 
      59                 : using namespace mozilla;
      60                 : 
      61                 : class txStylesheetCompilerState;
      62                 : 
      63                 : // ------------------------------------------------------------------
      64                 : // Utility functions
      65                 : // ------------------------------------------------------------------
      66                 : 
      67                 : static nsresult
      68               0 : convertRtfToNode(txIEvalContext *aContext, txResultTreeFragment *aRtf)
      69                 : {
      70                 :     txExecutionState* es = 
      71               0 :         static_cast<txExecutionState*>(aContext->getPrivateContext());
      72               0 :     if (!es) {
      73               0 :         NS_ERROR("Need txExecutionState!");
      74                 : 
      75               0 :         return NS_ERROR_UNEXPECTED;
      76                 :     }
      77                 : 
      78               0 :     const txXPathNode& document = es->getSourceDocument();
      79                 : 
      80               0 :     nsIDocument *doc = txXPathNativeNode::getDocument(document);
      81               0 :     nsCOMPtr<nsIDOMDocumentFragment> domFragment;
      82               0 :     nsresult rv = NS_NewDocumentFragment(getter_AddRefs(domFragment),
      83               0 :                                          doc->NodeInfoManager());
      84               0 :     NS_ENSURE_SUCCESS(rv, rv);
      85                 : 
      86               0 :     txOutputFormat format;
      87               0 :     txMozillaXMLOutput mozHandler(&format, domFragment, true);
      88                 : 
      89               0 :     rv = aRtf->flushToHandler(&mozHandler);
      90               0 :     NS_ENSURE_SUCCESS(rv, rv);
      91                 : 
      92               0 :     rv = mozHandler.closePrevious(true);
      93               0 :     NS_ENSURE_SUCCESS(rv, rv);
      94                 : 
      95                 :     // The txResultTreeFragment will own this.
      96                 :     const txXPathNode* node = txXPathNativeNode::createXPathNode(domFragment,
      97               0 :                                                                  true);
      98               0 :     NS_ENSURE_TRUE(node, NS_ERROR_OUT_OF_MEMORY);
      99                 : 
     100               0 :     aRtf->setNode(node);
     101                 : 
     102               0 :     return NS_OK;
     103                 : }
     104                 : 
     105                 : static nsresult
     106               0 : createTextNode(txIEvalContext *aContext, nsString& aValue,
     107                 :                txXPathNode* *aResult)
     108                 : {
     109                 :     txExecutionState* es = 
     110               0 :         static_cast<txExecutionState*>(aContext->getPrivateContext());
     111               0 :     if (!es) {
     112               0 :         NS_ERROR("Need txExecutionState!");
     113                 : 
     114               0 :         return NS_ERROR_UNEXPECTED;
     115                 :     }
     116                 : 
     117               0 :     const txXPathNode& document = es->getSourceDocument();
     118                 : 
     119               0 :     nsIDocument *doc = txXPathNativeNode::getDocument(document);
     120               0 :     nsCOMPtr<nsIContent> text;
     121               0 :     nsresult rv = NS_NewTextNode(getter_AddRefs(text), doc->NodeInfoManager());
     122               0 :     NS_ENSURE_SUCCESS(rv, rv);
     123                 : 
     124               0 :     rv = text->SetText(aValue, false);
     125               0 :     NS_ENSURE_SUCCESS(rv, rv);
     126                 : 
     127               0 :     *aResult = txXPathNativeNode::createXPathNode(text, true);
     128               0 :     NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
     129                 : 
     130               0 :     return NS_OK;
     131                 : }
     132                 : 
     133                 : static nsresult
     134               0 : createDocFragment(txIEvalContext *aContext, nsIContent** aResult)
     135                 : {
     136                 :     txExecutionState* es = 
     137               0 :         static_cast<txExecutionState*>(aContext->getPrivateContext());
     138               0 :     if (!es) {
     139               0 :         NS_ERROR("Need txExecutionState!");
     140                 : 
     141               0 :         return NS_ERROR_UNEXPECTED;
     142                 :     }
     143                 : 
     144               0 :     const txXPathNode& document = es->getSourceDocument();
     145               0 :     nsIDocument *doc = txXPathNativeNode::getDocument(document);
     146               0 :     nsCOMPtr<nsIDOMDocumentFragment> domFragment;
     147               0 :     nsresult rv = NS_NewDocumentFragment(getter_AddRefs(domFragment),
     148               0 :                                          doc->NodeInfoManager());
     149               0 :     NS_ENSURE_SUCCESS(rv, rv);
     150                 : 
     151               0 :     return CallQueryInterface(domFragment, aResult);
     152                 : }
     153                 : 
     154                 : static nsresult
     155               0 : createAndAddToResult(nsIAtom* aName, const nsSubstring& aValue,
     156                 :                      txNodeSet* aResultSet, nsIContent* aResultHolder)
     157                 : {
     158               0 :     NS_ASSERTION(aResultHolder->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT) &&
     159                 :                  aResultHolder->OwnerDoc(),
     160                 :                  "invalid result-holder");
     161                 : 
     162               0 :     nsIDocument* doc = aResultHolder->OwnerDoc();
     163               0 :     nsCOMPtr<nsIContent> elem;
     164               0 :     nsresult rv = doc->CreateElem(nsDependentAtomString(aName),
     165                 :                                   nsnull, kNameSpaceID_None,
     166               0 :                                   getter_AddRefs(elem));
     167               0 :     NS_ENSURE_SUCCESS(rv, rv);
     168                 : 
     169               0 :     nsCOMPtr<nsIContent> text;
     170               0 :     rv = NS_NewTextNode(getter_AddRefs(text), doc->NodeInfoManager());
     171               0 :     NS_ENSURE_SUCCESS(rv, rv);
     172                 : 
     173               0 :     rv = text->SetText(aValue, false);
     174               0 :     NS_ENSURE_SUCCESS(rv, rv);
     175                 : 
     176               0 :     rv = elem->AppendChildTo(text, false);
     177               0 :     NS_ENSURE_SUCCESS(rv, rv);
     178                 : 
     179               0 :     rv = aResultHolder->AppendChildTo(elem, false);
     180               0 :     NS_ENSURE_SUCCESS(rv, rv);
     181                 : 
     182                 :     nsAutoPtr<txXPathNode> xpathNode(
     183               0 :           txXPathNativeNode::createXPathNode(elem, true));
     184               0 :     NS_ENSURE_TRUE(xpathNode, NS_ERROR_OUT_OF_MEMORY);
     185                 : 
     186               0 :     aResultSet->append(*xpathNode);
     187                 : 
     188               0 :     return NS_OK;
     189                 : }
     190                 : 
     191                 : // Need to update this array if types are added to the ResultType enum in
     192                 : // txAExprResult.
     193                 : static const char * const sTypes[] = {
     194                 :   "node-set",
     195                 :   "boolean",
     196                 :   "number",
     197                 :   "string",
     198                 :   "RTF"
     199                 : };
     200                 : 
     201                 : // ------------------------------------------------------------------
     202                 : // Function implementations
     203                 : // ------------------------------------------------------------------
     204                 : 
     205                 : struct txEXSLTFunctionDescriptor
     206                 : {
     207                 :     PRInt8 mMinParams;
     208                 :     PRInt8 mMaxParams;
     209                 :     Expr::ResultType mReturnType;
     210                 :     nsIAtom** mName;
     211                 :     PRInt32 mNamespaceID;
     212                 :     const char* mNamespaceURI;
     213                 : };
     214                 : 
     215                 : static const char kEXSLTCommonNS[] = "http://exslt.org/common";
     216                 : static const char kEXSLTSetsNS[] = "http://exslt.org/sets";
     217                 : static const char kEXSLTStringsNS[] = "http://exslt.org/strings";
     218                 : static const char kEXSLTMathNS[] = "http://exslt.org/math";
     219                 : static const char kEXSLTDatesAndTimesNS[] = "http://exslt.org/dates-and-times";
     220                 : 
     221                 : // The order of this table must be the same as the
     222                 : // txEXSLTFunctionCall::eType enum
     223                 : static txEXSLTFunctionDescriptor descriptTable[] =
     224                 : {
     225                 :     { 1, 1, Expr::NODESET_RESULT, &nsGkAtoms::nodeSet, 0, kEXSLTCommonNS }, // NODE_SET
     226                 :     { 1, 1, Expr::STRING_RESULT,  &nsGkAtoms::objectType, 0, kEXSLTCommonNS }, // OBJECT_TYPE
     227                 :     { 2, 2, Expr::NODESET_RESULT, &nsGkAtoms::difference, 0, kEXSLTSetsNS }, // DIFFERENCE
     228                 :     { 1, 1, Expr::NODESET_RESULT, &nsGkAtoms::distinct, 0, kEXSLTSetsNS }, // DISTINCT
     229                 :     { 2, 2, Expr::BOOLEAN_RESULT, &nsGkAtoms::hasSameNode, 0, kEXSLTSetsNS }, // HAS_SAME_NODE
     230                 :     { 2, 2, Expr::NODESET_RESULT, &nsGkAtoms::intersection, 0, kEXSLTSetsNS }, // INTERSECTION
     231                 :     { 2, 2, Expr::NODESET_RESULT, &nsGkAtoms::leading, 0, kEXSLTSetsNS }, // LEADING
     232                 :     { 2, 2, Expr::NODESET_RESULT, &nsGkAtoms::trailing, 0, kEXSLTSetsNS }, // TRAILING
     233                 :     { 1, 1, Expr::STRING_RESULT,  &nsGkAtoms::concat, 0, kEXSLTStringsNS }, // CONCAT
     234                 :     { 1, 2, Expr::STRING_RESULT,  &nsGkAtoms::split, 0, kEXSLTStringsNS }, // SPLIT
     235                 :     { 1, 2, Expr::STRING_RESULT,  &nsGkAtoms::tokenize, 0, kEXSLTStringsNS }, // TOKENIZE
     236                 :     { 1, 1, Expr::NUMBER_RESULT,  &nsGkAtoms::max, 0, kEXSLTMathNS }, // MAX
     237                 :     { 1, 1, Expr::NUMBER_RESULT,  &nsGkAtoms::min, 0, kEXSLTMathNS }, // MIN
     238                 :     { 1, 1, Expr::NODESET_RESULT, &nsGkAtoms::highest, 0, kEXSLTMathNS }, // HIGHEST
     239                 :     { 1, 1, Expr::NODESET_RESULT, &nsGkAtoms::lowest, 0, kEXSLTMathNS }, // LOWEST
     240                 :     { 0, 0, Expr::STRING_RESULT,  &nsGkAtoms::dateTime, 0, kEXSLTDatesAndTimesNS }, // DATE_TIME
     241                 : 
     242                 : };
     243                 : 
     244                 : class txEXSLTFunctionCall : public FunctionCall
     245               0 : {
     246                 : public:
     247                 :     // The order of this enum must be the same as the descriptTable
     248                 :     // table above
     249                 :     enum eType {
     250                 :         // Set functions
     251                 :         NODE_SET,
     252                 :         OBJECT_TYPE,
     253                 :         DIFFERENCE,
     254                 :         DISTINCT,
     255                 :         HAS_SAME_NODE,
     256                 :         INTERSECTION,
     257                 :         LEADING,
     258                 :         TRAILING,
     259                 :         CONCAT,
     260                 :         SPLIT,
     261                 :         TOKENIZE,
     262                 :         MAX,
     263                 :         MIN,
     264                 :         HIGHEST,
     265                 :         LOWEST,
     266                 :         DATE_TIME
     267                 :     };
     268                 :     
     269               0 :     txEXSLTFunctionCall(eType aType)
     270               0 :       : mType(aType)
     271                 :     {
     272               0 :     }
     273                 : 
     274                 :     TX_DECL_FUNCTION
     275                 : 
     276                 : private:
     277                 :     eType mType;
     278                 : };
     279                 : 
     280                 : nsresult
     281               0 : txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
     282                 :                               txAExprResult **aResult)
     283                 : {
     284               0 :     *aResult = nsnull;
     285               0 :     if (!requireParams(descriptTable[mType].mMinParams,
     286                 :                        descriptTable[mType].mMaxParams,
     287               0 :                        aContext)) {
     288               0 :         return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
     289                 :     }
     290                 : 
     291               0 :     nsresult rv = NS_OK;
     292               0 :     switch (mType) {
     293                 :         case NODE_SET:
     294                 :         {
     295               0 :             nsRefPtr<txAExprResult> exprResult;
     296               0 :             rv = mParams[0]->evaluate(aContext, getter_AddRefs(exprResult));
     297               0 :             NS_ENSURE_SUCCESS(rv, rv);
     298                 : 
     299               0 :             if (exprResult->getResultType() == txAExprResult::NODESET) {
     300               0 :                 exprResult.swap(*aResult);
     301                 :             }
     302                 :             else {
     303               0 :                 nsRefPtr<txNodeSet> resultSet;
     304               0 :                 rv = aContext->recycler()->
     305               0 :                     getNodeSet(getter_AddRefs(resultSet));
     306               0 :                 NS_ENSURE_SUCCESS(rv, rv);
     307                 : 
     308               0 :                 if (exprResult->getResultType() ==
     309                 :                     txAExprResult::RESULT_TREE_FRAGMENT) {
     310                 :                     txResultTreeFragment *rtf =
     311                 :                         static_cast<txResultTreeFragment*>
     312               0 :                                    (exprResult.get());
     313                 : 
     314               0 :                     const txXPathNode *node = rtf->getNode();
     315               0 :                     if (!node) {
     316               0 :                         rv = convertRtfToNode(aContext, rtf);
     317               0 :                         NS_ENSURE_SUCCESS(rv, rv);
     318                 : 
     319               0 :                         node = rtf->getNode();
     320                 :                     }
     321                 : 
     322               0 :                     resultSet->append(*node);
     323                 :                 }
     324                 :                 else {
     325               0 :                     nsAutoString value;
     326               0 :                     exprResult->stringValue(value);
     327                 : 
     328               0 :                     nsAutoPtr<txXPathNode> node;
     329                 :                     rv = createTextNode(aContext, value,
     330               0 :                                         getter_Transfers(node));
     331               0 :                     NS_ENSURE_SUCCESS(rv, rv);
     332                 : 
     333               0 :                     resultSet->append(*node);
     334                 :                 }
     335                 : 
     336               0 :                 NS_ADDREF(*aResult = resultSet);
     337                 :             }
     338                 : 
     339               0 :             return NS_OK;
     340                 :         }
     341                 :         case OBJECT_TYPE:
     342                 :         {
     343               0 :             nsRefPtr<txAExprResult> exprResult;
     344               0 :             nsresult rv = mParams[0]->evaluate(aContext,
     345               0 :                                                getter_AddRefs(exprResult));
     346               0 :             NS_ENSURE_SUCCESS(rv, rv);
     347                 : 
     348               0 :             nsRefPtr<StringResult> strRes;
     349               0 :             rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
     350               0 :             NS_ENSURE_SUCCESS(rv, rv);
     351                 : 
     352               0 :             AppendASCIItoUTF16(sTypes[exprResult->getResultType()],
     353               0 :                                strRes->mValue);
     354                 : 
     355               0 :             NS_ADDREF(*aResult = strRes);
     356                 : 
     357               0 :             return NS_OK;
     358                 :         }
     359                 :         case DIFFERENCE:
     360                 :         case INTERSECTION:
     361                 :         {
     362               0 :             nsRefPtr<txNodeSet> nodes1;
     363               0 :             rv = evaluateToNodeSet(mParams[0], aContext,
     364               0 :                                    getter_AddRefs(nodes1));
     365               0 :             NS_ENSURE_SUCCESS(rv, rv);
     366                 : 
     367               0 :             nsRefPtr<txNodeSet> nodes2;
     368               0 :             rv = evaluateToNodeSet(mParams[1], aContext,
     369               0 :                                    getter_AddRefs(nodes2));
     370               0 :             NS_ENSURE_SUCCESS(rv, rv);
     371                 : 
     372               0 :             nsRefPtr<txNodeSet> resultSet;
     373               0 :             rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
     374               0 :             NS_ENSURE_SUCCESS(rv, rv);
     375                 : 
     376               0 :             bool insertOnFound = mType == INTERSECTION;
     377                 : 
     378               0 :             PRInt32 searchPos = 0;
     379               0 :             PRInt32 i, len = nodes1->size();
     380               0 :             for (i = 0; i < len; ++i) {
     381               0 :                 const txXPathNode& node = nodes1->get(i);
     382               0 :                 PRInt32 foundPos = nodes2->indexOf(node, searchPos);
     383               0 :                 if (foundPos >= 0) {
     384               0 :                     searchPos = foundPos + 1;
     385                 :                 }
     386                 : 
     387               0 :                 if ((foundPos >= 0) == insertOnFound) {
     388               0 :                     rv = resultSet->append(node);
     389               0 :                     NS_ENSURE_SUCCESS(rv, rv);
     390                 :                 }
     391                 :             }
     392                 : 
     393               0 :             NS_ADDREF(*aResult = resultSet);
     394                 : 
     395               0 :             return NS_OK;
     396                 :         }
     397                 :         case DISTINCT:
     398                 :         {
     399               0 :             nsRefPtr<txNodeSet> nodes;
     400               0 :             rv = evaluateToNodeSet(mParams[0], aContext,
     401               0 :                                    getter_AddRefs(nodes));
     402               0 :             NS_ENSURE_SUCCESS(rv, rv);
     403                 : 
     404               0 :             nsRefPtr<txNodeSet> resultSet;
     405               0 :             rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
     406               0 :             NS_ENSURE_SUCCESS(rv, rv);
     407                 : 
     408               0 :             nsTHashtable<nsStringHashKey> hash;
     409               0 :             if (!hash.Init()) {
     410               0 :                 return NS_ERROR_OUT_OF_MEMORY;
     411                 :             }
     412                 : 
     413               0 :             PRInt32 i, len = nodes->size();
     414               0 :             for (i = 0; i < len; ++i) {
     415               0 :                 nsAutoString str;
     416               0 :                 const txXPathNode& node = nodes->get(i);
     417               0 :                 txXPathNodeUtils::appendNodeValue(node, str);
     418               0 :                 if (!hash.GetEntry(str)) {
     419               0 :                     if (!hash.PutEntry(str)) {
     420               0 :                         return NS_ERROR_OUT_OF_MEMORY;
     421                 :                     }
     422               0 :                     rv = resultSet->append(node);
     423               0 :                     NS_ENSURE_SUCCESS(rv, rv);
     424                 :                 }
     425                 :             }
     426                 : 
     427               0 :             NS_ADDREF(*aResult = resultSet);
     428                 : 
     429               0 :             return NS_OK;
     430                 :         }
     431                 :         case HAS_SAME_NODE:
     432                 :         {
     433               0 :             nsRefPtr<txNodeSet> nodes1;
     434               0 :             rv = evaluateToNodeSet(mParams[0], aContext,
     435               0 :                                    getter_AddRefs(nodes1));
     436               0 :             NS_ENSURE_SUCCESS(rv, rv);
     437                 : 
     438               0 :             nsRefPtr<txNodeSet> nodes2;
     439               0 :             rv = evaluateToNodeSet(mParams[1], aContext,
     440               0 :                                    getter_AddRefs(nodes2));
     441               0 :             NS_ENSURE_SUCCESS(rv, rv);
     442                 : 
     443               0 :             bool found = false;
     444               0 :             PRInt32 i, len = nodes1->size();
     445               0 :             for (i = 0; i < len; ++i) {
     446               0 :                 if (nodes2->contains(nodes1->get(i))) {
     447               0 :                     found = true;
     448               0 :                     break;
     449                 :                 }
     450                 :             }
     451                 : 
     452               0 :             aContext->recycler()->getBoolResult(found, aResult);
     453                 : 
     454               0 :             return NS_OK;
     455                 :         }
     456                 :         case LEADING:
     457                 :         case TRAILING:
     458                 :         {
     459               0 :             nsRefPtr<txNodeSet> nodes1;
     460               0 :             rv = evaluateToNodeSet(mParams[0], aContext,
     461               0 :                                    getter_AddRefs(nodes1));
     462               0 :             NS_ENSURE_SUCCESS(rv, rv);
     463                 : 
     464               0 :             nsRefPtr<txNodeSet> nodes2;
     465               0 :             rv = evaluateToNodeSet(mParams[1], aContext,
     466               0 :                                    getter_AddRefs(nodes2));
     467               0 :             NS_ENSURE_SUCCESS(rv, rv);
     468                 : 
     469               0 :             if (nodes2->isEmpty()) {
     470               0 :                 *aResult = nodes1;
     471               0 :                 NS_ADDREF(*aResult);
     472                 : 
     473               0 :                 return NS_OK;
     474                 :             }
     475                 : 
     476               0 :             nsRefPtr<txNodeSet> resultSet;
     477               0 :             rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
     478               0 :             NS_ENSURE_SUCCESS(rv, rv);
     479                 : 
     480               0 :             PRInt32 end = nodes1->indexOf(nodes2->get(0));
     481               0 :             if (end >= 0) {
     482               0 :                 PRInt32 i = 0;
     483               0 :                 if (mType == TRAILING) {
     484               0 :                     i = end + 1;
     485               0 :                     end = nodes1->size();
     486                 :                 }
     487               0 :                 for (; i < end; ++i) {
     488               0 :                     rv = resultSet->append(nodes1->get(i));
     489               0 :                     NS_ENSURE_SUCCESS(rv, rv);
     490                 :                 }
     491                 :             }
     492                 : 
     493               0 :             NS_ADDREF(*aResult = resultSet);
     494                 : 
     495               0 :             return NS_OK;
     496                 :         }
     497                 :         case CONCAT:
     498                 :         {
     499               0 :             nsRefPtr<txNodeSet> nodes;
     500               0 :             rv = evaluateToNodeSet(mParams[0], aContext,
     501               0 :                                    getter_AddRefs(nodes));
     502               0 :             NS_ENSURE_SUCCESS(rv, rv);
     503                 : 
     504               0 :             nsAutoString str;
     505               0 :             PRInt32 i, len = nodes->size();
     506               0 :             for (i = 0; i < len; ++i) {
     507               0 :                 txXPathNodeUtils::appendNodeValue(nodes->get(i), str);
     508                 :             }
     509                 : 
     510               0 :             return aContext->recycler()->getStringResult(str, aResult);
     511                 :         }
     512                 :         case SPLIT:
     513                 :         case TOKENIZE:
     514                 :         {
     515                 :             // Evaluate parameters
     516               0 :             nsAutoString string;
     517               0 :             rv = mParams[0]->evaluateToString(aContext, string);
     518               0 :             NS_ENSURE_SUCCESS(rv, rv);
     519                 : 
     520               0 :             nsAutoString pattern;
     521               0 :             if (mParams.Length() == 2) {
     522               0 :                 rv = mParams[1]->evaluateToString(aContext, pattern);
     523               0 :                 NS_ENSURE_SUCCESS(rv, rv);
     524                 :             }
     525               0 :             else if (mType == SPLIT) {
     526               0 :                 pattern.AssignLiteral(" ");
     527                 :             }
     528                 :             else {
     529               0 :                 pattern.AssignLiteral("\t\r\n ");
     530                 :             }
     531                 : 
     532                 :             // Set up holders for the result
     533               0 :             nsCOMPtr<nsIContent> docFrag;
     534               0 :             rv = createDocFragment(aContext, getter_AddRefs(docFrag));
     535               0 :             NS_ENSURE_SUCCESS(rv, rv);
     536                 : 
     537               0 :             nsRefPtr<txNodeSet> resultSet;
     538               0 :             rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
     539               0 :             NS_ENSURE_SUCCESS(rv, rv);
     540                 : 
     541                 :             PRUint32 tailIndex;
     542                 : 
     543                 :             // Start splitting
     544               0 :             if (pattern.IsEmpty()) {
     545               0 :                 nsString::const_char_iterator start = string.BeginReading();
     546               0 :                 nsString::const_char_iterator end = string.EndReading();
     547               0 :                 for (; start < end; ++start) {
     548                 :                     rv = createAndAddToResult(nsGkAtoms::token,
     549               0 :                                               Substring(start, start + 1),
     550               0 :                                               resultSet, docFrag);
     551               0 :                     NS_ENSURE_SUCCESS(rv, rv);
     552                 :                 }
     553                 : 
     554               0 :                 tailIndex = string.Length();
     555                 :             }
     556               0 :             else if (mType == SPLIT) {
     557               0 :                 nsAString::const_iterator strStart, strEnd;
     558               0 :                 string.BeginReading(strStart);
     559               0 :                 string.EndReading(strEnd);
     560               0 :                 nsAString::const_iterator start = strStart, end = strEnd;
     561                 : 
     562               0 :                 while (FindInReadable(pattern, start, end)) {
     563               0 :                     if (start != strStart) {
     564                 :                         rv = createAndAddToResult(nsGkAtoms::token,
     565               0 :                                                   Substring(strStart, start),
     566               0 :                                                   resultSet, docFrag);
     567               0 :                         NS_ENSURE_SUCCESS(rv, rv);
     568                 :                     }
     569               0 :                     strStart = start = end;
     570               0 :                     end = strEnd;
     571                 :                 }
     572                 : 
     573               0 :                 tailIndex = strStart.get() - string.get();
     574                 :             }
     575                 :             else {
     576               0 :                 PRInt32 found, start = 0;
     577               0 :                 while ((found = string.FindCharInSet(pattern, start)) !=
     578                 :                        kNotFound) {
     579               0 :                     if (found != start) {
     580                 :                         rv = createAndAddToResult(nsGkAtoms::token,
     581                 :                                                   Substring(string, start,
     582               0 :                                                             found - start),
     583               0 :                                                   resultSet, docFrag);
     584               0 :                         NS_ENSURE_SUCCESS(rv, rv);
     585                 :                     }
     586               0 :                     start = found + 1;
     587                 :                 }
     588                 : 
     589               0 :                 tailIndex = start;
     590                 :             }
     591                 : 
     592                 :             // Add tail if needed
     593               0 :             if (tailIndex != (PRUint32)string.Length()) {
     594                 :                 rv = createAndAddToResult(nsGkAtoms::token,
     595               0 :                                           Substring(string, tailIndex),
     596               0 :                                           resultSet, docFrag);
     597               0 :                 NS_ENSURE_SUCCESS(rv, rv);
     598                 :             }
     599                 : 
     600               0 :             NS_ADDREF(*aResult = resultSet);
     601                 : 
     602               0 :             return NS_OK;
     603                 :         }
     604                 :         case MAX:
     605                 :         case MIN:
     606                 :         {
     607               0 :             nsRefPtr<txNodeSet> nodes;
     608               0 :             rv = evaluateToNodeSet(mParams[0], aContext,
     609               0 :                                    getter_AddRefs(nodes));
     610               0 :             NS_ENSURE_SUCCESS(rv, rv);
     611                 : 
     612               0 :             if (nodes->isEmpty()) {
     613               0 :                 return aContext->recycler()->
     614               0 :                     getNumberResult(txDouble::NaN, aResult);
     615                 :             }
     616                 : 
     617               0 :             bool findMax = mType == MAX;
     618                 : 
     619                 :             double res = findMax ? txDouble::NEGATIVE_INFINITY :
     620               0 :                                    txDouble::POSITIVE_INFINITY;
     621               0 :             PRInt32 i, len = nodes->size();
     622               0 :             for (i = 0; i < len; ++i) {
     623               0 :                 nsAutoString str;
     624               0 :                 txXPathNodeUtils::appendNodeValue(nodes->get(i), str);
     625               0 :                 double val = txDouble::toDouble(str);
     626               0 :                 if (txDouble::isNaN(val)) {
     627               0 :                     res = txDouble::NaN;
     628                 :                     break;
     629                 :                 }
     630                 : 
     631               0 :                 if (findMax ? (val > res) : (val < res)) {
     632               0 :                     res = val;
     633                 :                 }
     634                 :             }
     635                 : 
     636               0 :             return aContext->recycler()->getNumberResult(res, aResult);
     637                 :         }
     638                 :         case HIGHEST:
     639                 :         case LOWEST:
     640                 :         {
     641               0 :             nsRefPtr<txNodeSet> nodes;
     642               0 :             rv = evaluateToNodeSet(mParams[0], aContext,
     643               0 :                                    getter_AddRefs(nodes));
     644               0 :             NS_ENSURE_SUCCESS(rv, rv);
     645                 : 
     646               0 :             if (nodes->isEmpty()) {
     647               0 :                 NS_ADDREF(*aResult = nodes);
     648                 : 
     649               0 :                 return NS_OK;
     650                 :             }
     651                 : 
     652               0 :             nsRefPtr<txNodeSet> resultSet;
     653               0 :             rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
     654               0 :             NS_ENSURE_SUCCESS(rv, rv);
     655                 : 
     656               0 :             bool findMax = mType == HIGHEST;
     657                 :             double res = findMax ? txDouble::NEGATIVE_INFINITY :
     658               0 :                                    txDouble::POSITIVE_INFINITY;
     659               0 :             PRInt32 i, len = nodes->size();
     660               0 :             for (i = 0; i < len; ++i) {
     661               0 :                 nsAutoString str;
     662               0 :                 const txXPathNode& node = nodes->get(i);
     663               0 :                 txXPathNodeUtils::appendNodeValue(node, str);
     664               0 :                 double val = txDouble::toDouble(str);
     665               0 :                 if (txDouble::isNaN(val)) {
     666               0 :                     resultSet->clear();
     667                 :                     break;
     668                 :                 }
     669               0 :                 if (findMax ? (val > res) : (val < res)) {
     670               0 :                     resultSet->clear();
     671               0 :                     res = val;
     672                 :                 }
     673                 : 
     674               0 :                 if (res == val) {
     675               0 :                     rv = resultSet->append(node);
     676               0 :                     NS_ENSURE_SUCCESS(rv, rv);
     677                 :                 }
     678                 :             }
     679                 : 
     680               0 :             NS_ADDREF(*aResult = resultSet);
     681                 : 
     682               0 :             return NS_OK;
     683                 :         }
     684                 :         case DATE_TIME:
     685                 :         {
     686                 :             // http://exslt.org/date/functions/date-time/
     687                 :             // format: YYYY-MM-DDTTHH:MM:SS.sss+00:00
     688               0 :             char formatstr[] = "%04hd-%02ld-%02ldT%02ld:%02ld:%02ld.%03ld%c%02ld:%02ld";
     689               0 :             const size_t max = sizeof("YYYY-MM-DDTHH:MM:SS.sss+00:00");
     690                 :             
     691                 :             PRExplodedTime prtime;
     692               0 :             PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &prtime);
     693                 :             
     694                 :             PRInt32 offset = (prtime.tm_params.tp_gmt_offset +
     695               0 :               prtime.tm_params.tp_dst_offset) / 60;
     696                 :               
     697               0 :             bool isneg = offset < 0;
     698               0 :             if (isneg) offset = -offset;
     699                 :             
     700                 :             StringResult* strRes;
     701               0 :             rv = aContext->recycler()->getStringResult(&strRes);
     702               0 :             NS_ENSURE_SUCCESS(rv, rv);
     703                 :             
     704                 :             CopyASCIItoUTF16(nsPrintfCString(max, formatstr,
     705                 :               prtime.tm_year, prtime.tm_month + 1, prtime.tm_mday,
     706                 :               prtime.tm_hour, prtime.tm_min, prtime.tm_sec,
     707                 :               prtime.tm_usec / 10000,
     708               0 :               isneg ? '-' : '+', offset / 60, offset % 60), strRes->mValue);
     709                 :               
     710               0 :             *aResult = strRes;
     711                 : 
     712               0 :             return NS_OK;
     713                 :         }
     714                 :     }
     715                 : 
     716                 :     aContext->receiveError(NS_LITERAL_STRING("Internal error"),
     717                 :                            NS_ERROR_UNEXPECTED);
     718                 :     return NS_ERROR_UNEXPECTED;
     719                 : }
     720                 : 
     721                 : Expr::ResultType
     722               0 : txEXSLTFunctionCall::getReturnType()
     723                 : {
     724               0 :     return descriptTable[mType].mReturnType;
     725                 : }
     726                 : 
     727                 : bool
     728               0 : txEXSLTFunctionCall::isSensitiveTo(ContextSensitivity aContext)
     729                 : {
     730               0 :     if (mType == NODE_SET || mType == SPLIT || mType == TOKENIZE) {
     731               0 :         return (aContext & PRIVATE_CONTEXT) || argsSensitiveTo(aContext);
     732                 :     }
     733               0 :     return argsSensitiveTo(aContext);
     734                 : }
     735                 : 
     736                 : #ifdef TX_TO_STRING
     737                 : nsresult
     738               0 : txEXSLTFunctionCall::getNameAtom(nsIAtom **aAtom)
     739                 : {
     740               0 :     NS_ADDREF(*aAtom = *descriptTable[mType].mName);
     741               0 :     return NS_OK;
     742                 : }
     743                 : #endif
     744                 : 
     745                 : extern nsresult
     746               0 : TX_ConstructEXSLTFunction(nsIAtom *aName,
     747                 :                           PRInt32 aNamespaceID,
     748                 :                           txStylesheetCompilerState* aState,
     749                 :                           FunctionCall **aResult)
     750                 : {
     751                 :     PRUint32 i;
     752               0 :     for (i = 0; i < ArrayLength(descriptTable); ++i) {
     753               0 :         txEXSLTFunctionDescriptor& desc = descriptTable[i];
     754               0 :         if (aName == *desc.mName && aNamespaceID == desc.mNamespaceID) {
     755                 :             *aResult = new txEXSLTFunctionCall(
     756               0 :                 static_cast<txEXSLTFunctionCall::eType>(i));
     757                 : 
     758               0 :             return *aResult ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
     759                 :         }
     760                 :     }
     761                 : 
     762               0 :     return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
     763                 : }
     764                 : 
     765                 : extern bool
     766            1404 : TX_InitEXSLTFunction()
     767                 : {
     768                 :     PRUint32 i;
     769           23868 :     for (i = 0; i < ArrayLength(descriptTable); ++i) {
     770           22464 :         txEXSLTFunctionDescriptor& desc = descriptTable[i];
     771           44928 :         NS_ConvertASCIItoUTF16 namespaceURI(desc.mNamespaceURI);
     772                 :         desc.mNamespaceID =
     773           22464 :             txNamespaceManager::getNamespaceID(namespaceURI);
     774                 : 
     775           22464 :         if (desc.mNamespaceID == kNameSpaceID_Unknown) {
     776               0 :             return false;
     777                 :         }
     778                 :     }
     779                 : 
     780            1404 :     return true;
     781                 : }

Generated by: LCOV version 1.7