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

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "txPatternParser.h"
       7             : #include "txExprLexer.h"
       8             : #include "nsGkAtoms.h"
       9             : #include "nsError.h"
      10             : #include "txStringUtils.h"
      11             : #include "txXSLTPatterns.h"
      12             : #include "txStylesheetCompiler.h"
      13             : #include "txPatternOptimizer.h"
      14             : 
      15             : 
      16           0 : nsresult txPatternParser::createPattern(const nsString& aPattern,
      17             :                                         txIParseContext* aContext,
      18             :                                         txPattern** aResult)
      19             : {
      20           0 :     txExprLexer lexer;
      21           0 :     nsresult rv = lexer.parse(aPattern);
      22           0 :     if (NS_FAILED(rv)) {
      23             :         // XXX error report parsing error
      24           0 :         return rv;
      25             :     }
      26           0 :     nsAutoPtr<txPattern> pattern;
      27           0 :     rv = createUnionPattern(lexer, aContext, *getter_Transfers(pattern));
      28           0 :     if (NS_FAILED(rv)) {
      29             :         // XXX error report parsing error
      30           0 :         return rv;
      31             :     }
      32             : 
      33             :     txPatternOptimizer optimizer;
      34           0 :     txPattern* newPattern = nullptr;
      35           0 :     rv = optimizer.optimize(pattern, &newPattern);
      36           0 :     NS_ENSURE_SUCCESS(rv, rv);
      37             : 
      38           0 :     *aResult = newPattern ? newPattern : pattern.forget();
      39             : 
      40           0 :     return NS_OK;
      41             : }
      42             : 
      43           0 : nsresult txPatternParser::createUnionPattern(txExprLexer& aLexer,
      44             :                                              txIParseContext* aContext,
      45             :                                              txPattern*& aPattern)
      46             : {
      47           0 :     nsresult rv = NS_OK;
      48           0 :     txPattern* locPath = 0;
      49             : 
      50           0 :     rv = createLocPathPattern(aLexer, aContext, locPath);
      51           0 :     if (NS_FAILED(rv))
      52           0 :         return rv;
      53             : 
      54           0 :     Token::Type type = aLexer.peek()->mType;
      55           0 :     if (type == Token::END) {
      56           0 :         aPattern = locPath;
      57           0 :         return NS_OK;
      58             :     }
      59             : 
      60           0 :     if (type != Token::UNION_OP) {
      61           0 :         delete locPath;
      62           0 :         return NS_ERROR_XPATH_PARSE_FAILURE;
      63             :     }
      64             : 
      65           0 :     txUnionPattern* unionPattern = new txUnionPattern();
      66           0 :     rv = unionPattern->addPattern(locPath);
      67             : #if 0 // XXX addPattern can't fail yet, it doesn't check for mem
      68             :     if (NS_FAILED(rv)) {
      69             :         delete unionPattern;
      70             :         delete locPath;
      71             :         return rv;
      72             :     }
      73             : #endif
      74             : 
      75           0 :     aLexer.nextToken();
      76           0 :     do {
      77           0 :         rv = createLocPathPattern(aLexer, aContext, locPath);
      78           0 :         if (NS_FAILED(rv)) {
      79           0 :             delete unionPattern;
      80           0 :             return rv;
      81             :         }
      82           0 :         rv = unionPattern->addPattern(locPath);
      83             : #if 0 // XXX addPattern can't fail yet, it doesn't check for mem
      84             :         if (NS_FAILED(rv)) {
      85             :             delete unionPattern;
      86             :             delete locPath;
      87             :             return rv;
      88             :         }
      89             : #endif
      90           0 :         type = aLexer.nextToken()->mType;
      91           0 :     } while (type == Token::UNION_OP);
      92             : 
      93           0 :     if (type != Token::END) {
      94           0 :         delete unionPattern;
      95           0 :         return NS_ERROR_XPATH_PARSE_FAILURE;
      96             :     }
      97             : 
      98           0 :     aPattern = unionPattern;
      99           0 :     return NS_OK;
     100             : }
     101             : 
     102           0 : nsresult txPatternParser::createLocPathPattern(txExprLexer& aLexer,
     103             :                                                txIParseContext* aContext,
     104             :                                                txPattern*& aPattern)
     105             : {
     106           0 :     nsresult rv = NS_OK;
     107             : 
     108           0 :     bool isChild = true;
     109           0 :     bool isAbsolute = false;
     110           0 :     txPattern* stepPattern = 0;
     111           0 :     txLocPathPattern* pathPattern = 0;
     112             : 
     113           0 :     Token::Type type = aLexer.peek()->mType;
     114           0 :     switch (type) {
     115             :         case Token::ANCESTOR_OP:
     116           0 :             isChild = false;
     117           0 :             isAbsolute = true;
     118           0 :             aLexer.nextToken();
     119           0 :             break;
     120             :         case Token::PARENT_OP:
     121           0 :             aLexer.nextToken();
     122           0 :             isAbsolute = true;
     123           0 :             if (aLexer.peek()->mType == Token::END ||
     124           0 :                 aLexer.peek()->mType == Token::UNION_OP) {
     125           0 :                 aPattern = new txRootPattern();
     126           0 :                 return NS_OK;
     127             :             }
     128           0 :             break;
     129             :         case Token::FUNCTION_NAME_AND_PAREN:
     130             :             // id(Literal) or key(Literal, Literal)
     131             :             {
     132             :                 nsCOMPtr<nsIAtom> nameAtom =
     133           0 :                     NS_Atomize(aLexer.nextToken()->Value());
     134           0 :                 if (nameAtom == nsGkAtoms::id) {
     135           0 :                     rv = createIdPattern(aLexer, stepPattern);
     136             :                 }
     137           0 :                 else if (nameAtom == nsGkAtoms::key) {
     138           0 :                     rv = createKeyPattern(aLexer, aContext, stepPattern);
     139             :                 }
     140           0 :                 if (NS_FAILED(rv))
     141           0 :                     return rv;
     142             :             }
     143           0 :             break;
     144             :         default:
     145           0 :             break;
     146             :     }
     147           0 :     if (!stepPattern) {
     148           0 :         rv = createStepPattern(aLexer, aContext, stepPattern);
     149           0 :         if (NS_FAILED(rv))
     150           0 :             return rv;
     151             :     }
     152             : 
     153           0 :     type = aLexer.peek()->mType;
     154           0 :     if (!isAbsolute && type != Token::PARENT_OP
     155           0 :         && type != Token::ANCESTOR_OP) {
     156           0 :         aPattern = stepPattern;
     157           0 :         return NS_OK;
     158             :     }
     159             : 
     160           0 :     pathPattern = new txLocPathPattern();
     161           0 :     if (isAbsolute) {
     162           0 :         txRootPattern* root = new txRootPattern();
     163             : #ifdef TX_TO_STRING
     164           0 :         root->setSerialize(false);
     165             : #endif
     166             : 
     167           0 :         rv = pathPattern->addStep(root, isChild);
     168           0 :         if (NS_FAILED(rv)) {
     169           0 :             delete stepPattern;
     170           0 :             delete pathPattern;
     171           0 :             delete root;
     172           0 :             return NS_ERROR_OUT_OF_MEMORY;
     173             :         }
     174             :     }
     175             : 
     176           0 :     rv = pathPattern->addStep(stepPattern, isChild);
     177           0 :     if (NS_FAILED(rv)) {
     178           0 :         delete stepPattern;
     179           0 :         delete pathPattern;
     180           0 :         return NS_ERROR_OUT_OF_MEMORY;
     181             :     }
     182           0 :     stepPattern = 0; // stepPattern is part of pathPattern now
     183             : 
     184           0 :     while (type == Token::PARENT_OP || type == Token::ANCESTOR_OP) {
     185           0 :         isChild = type == Token::PARENT_OP;
     186           0 :         aLexer.nextToken();
     187           0 :         rv = createStepPattern(aLexer, aContext, stepPattern);
     188           0 :         if (NS_FAILED(rv)) {
     189           0 :             delete pathPattern;
     190           0 :             return rv;
     191             :         }
     192           0 :         rv = pathPattern->addStep(stepPattern, isChild);
     193           0 :         if (NS_FAILED(rv)) {
     194           0 :             delete stepPattern;
     195           0 :             delete pathPattern;
     196           0 :             return NS_ERROR_OUT_OF_MEMORY;
     197             :         }
     198           0 :         stepPattern = 0; // stepPattern is part of pathPattern now
     199           0 :         type = aLexer.peek()->mType;
     200             :     }
     201           0 :     aPattern = pathPattern;
     202           0 :     return rv;
     203             : }
     204             : 
     205           0 : nsresult txPatternParser::createIdPattern(txExprLexer& aLexer,
     206             :                                           txPattern*& aPattern)
     207             : {
     208             :     // check for '(' Literal ')'
     209           0 :     if (aLexer.peek()->mType != Token::LITERAL)
     210           0 :         return NS_ERROR_XPATH_PARSE_FAILURE;
     211             :     const nsDependentSubstring& value =
     212           0 :         aLexer.nextToken()->Value();
     213           0 :     if (aLexer.nextToken()->mType != Token::R_PAREN)
     214           0 :         return NS_ERROR_XPATH_PARSE_FAILURE;
     215           0 :     aPattern  = new txIdPattern(value);
     216           0 :     return NS_OK;
     217             : }
     218             : 
     219           0 : nsresult txPatternParser::createKeyPattern(txExprLexer& aLexer,
     220             :                                            txIParseContext* aContext,
     221             :                                            txPattern*& aPattern)
     222             : {
     223             :     // check for '(' Literal, Literal ')'
     224           0 :     if (aLexer.peek()->mType != Token::LITERAL)
     225           0 :         return NS_ERROR_XPATH_PARSE_FAILURE;
     226             :     const nsDependentSubstring& key =
     227           0 :         aLexer.nextToken()->Value();
     228           0 :     if (aLexer.nextToken()->mType != Token::COMMA &&
     229           0 :         aLexer.peek()->mType != Token::LITERAL)
     230           0 :         return NS_ERROR_XPATH_PARSE_FAILURE;
     231             :     const nsDependentSubstring& value =
     232           0 :         aLexer.nextToken()->Value();
     233           0 :     if (aLexer.nextToken()->mType != Token::R_PAREN)
     234           0 :         return NS_ERROR_XPATH_PARSE_FAILURE;
     235             : 
     236           0 :     if (!aContext->allowed(txIParseContext::KEY_FUNCTION))
     237           0 :         return NS_ERROR_XSLT_CALL_TO_KEY_NOT_ALLOWED;
     238             : 
     239             :     const char16_t* colon;
     240           0 :     if (!XMLUtils::isValidQName(PromiseFlatString(key), &colon))
     241           0 :         return NS_ERROR_XPATH_PARSE_FAILURE;
     242           0 :     nsCOMPtr<nsIAtom> prefix, localName;
     243             :     int32_t namespaceID;
     244           0 :     nsresult rv = resolveQName(key, getter_AddRefs(prefix), aContext,
     245           0 :                                getter_AddRefs(localName), namespaceID);
     246           0 :     if (NS_FAILED(rv))
     247           0 :         return rv;
     248             : 
     249           0 :     aPattern  = new txKeyPattern(prefix, localName, namespaceID, value);
     250           0 :     return NS_OK;
     251             : }
     252             : 
     253           0 : nsresult txPatternParser::createStepPattern(txExprLexer& aLexer,
     254             :                                             txIParseContext* aContext,
     255             :                                             txPattern*& aPattern)
     256             : {
     257           0 :     nsresult rv = NS_OK;
     258           0 :     bool isAttr = false;
     259           0 :     Token* tok = aLexer.peek();
     260           0 :     if (tok->mType == Token::AXIS_IDENTIFIER) {
     261           0 :         if (TX_StringEqualsAtom(tok->Value(), nsGkAtoms::attribute)) {
     262           0 :             isAttr = true;
     263             :         }
     264           0 :         else if (!TX_StringEqualsAtom(tok->Value(), nsGkAtoms::child)) {
     265             :             // all done already for CHILD_AXIS, for all others
     266             :             // XXX report unexpected axis error
     267           0 :             return NS_ERROR_XPATH_PARSE_FAILURE;
     268             :         }
     269           0 :         aLexer.nextToken();
     270             :     }
     271           0 :     else if (tok->mType == Token::AT_SIGN) {
     272           0 :         aLexer.nextToken();
     273           0 :         isAttr = true;
     274             :     }
     275             : 
     276             :     txNodeTest* nodeTest;
     277           0 :     if (aLexer.peek()->mType == Token::CNAME) {
     278           0 :         tok = aLexer.nextToken();
     279             : 
     280             :         // resolve QName
     281           0 :         nsCOMPtr<nsIAtom> prefix, lName;
     282             :         int32_t nspace;
     283           0 :         rv = resolveQName(tok->Value(), getter_AddRefs(prefix), aContext,
     284           0 :                           getter_AddRefs(lName), nspace, true);
     285           0 :         if (NS_FAILED(rv)) {
     286             :             // XXX error report namespace resolve failed
     287           0 :             return rv;
     288             :         }
     289             : 
     290           0 :         uint16_t nodeType = isAttr ?
     291             :                             (uint16_t)txXPathNodeType::ATTRIBUTE_NODE :
     292           0 :                             (uint16_t)txXPathNodeType::ELEMENT_NODE;
     293           0 :         nodeTest = new txNameTest(prefix, lName, nspace, nodeType);
     294             :     }
     295             :     else {
     296           0 :         rv = createNodeTypeTest(aLexer, &nodeTest);
     297           0 :         NS_ENSURE_SUCCESS(rv, rv);
     298             :     }
     299             : 
     300           0 :     nsAutoPtr<txStepPattern> step(new txStepPattern(nodeTest, isAttr));
     301           0 :     rv = parsePredicates(step, aLexer, aContext);
     302           0 :     NS_ENSURE_SUCCESS(rv, rv);
     303             : 
     304           0 :     aPattern = step.forget();
     305             : 
     306           0 :     return NS_OK;
     307             : }

Generated by: LCOV version 1.13