diff options
Diffstat (limited to 'Source/WebCore/xml/XPathParser.cpp')
-rw-r--r-- | Source/WebCore/xml/XPathParser.cpp | 347 |
1 files changed, 98 insertions, 249 deletions
diff --git a/Source/WebCore/xml/XPathParser.cpp b/Source/WebCore/xml/XPathParser.cpp index 749180dbe..c30e9fb1f 100644 --- a/Source/WebCore/xml/XPathParser.cpp +++ b/Source/WebCore/xml/XPathParser.cpp @@ -1,6 +1,6 @@ /* * Copyright 2005 Maksim Orlovich <maksim@kde.org> - * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006, 2013 Apple Inc. All rights reserved. * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> * * Redistribution and use in source and binary forms, with or without @@ -33,42 +33,52 @@ #include "XPathException.h" #include "XPathNSResolver.h" #include "XPathPath.h" -#include "XPathStep.h" +#include <wtf/NeverDestroyed.h> #include <wtf/StdLibExtras.h> #include <wtf/text/StringHash.h> using namespace WebCore; -using namespace WTF; -using namespace Unicode; using namespace XPath; -extern int xpathyyparse(WebCore::XPath::Parser*); +extern int xpathyyparse(Parser&); + #include "XPathGrammar.h" -Parser* Parser::currentParser = 0; +namespace WebCore { +namespace XPath { -enum XMLCat { NameStart, NameCont, NotPartOfName }; +struct Parser::Token { + int type; + String string; + Step::Axis axis; + NumericOp::Opcode numericOpcode; + EqTestOp::Opcode equalityTestOpcode; -typedef HashMap<String, Step::Axis> AxisNamesMap; + Token(int type) : type(type) { } + Token(int type, const String& string) : type(type), string(string) { } + Token(int type, Step::Axis axis) : type(type), axis(axis) { } + Token(int type, NumericOp::Opcode opcode) : type(type), numericOpcode(opcode) { } + Token(int type, EqTestOp::Opcode opcode) : type(type), equalityTestOpcode(opcode) { } +}; -static XMLCat charCat(UChar aChar) -{ - //### might need to add some special cases from the XML spec. +enum XMLCat { NameStart, NameCont, NotPartOfName }; - if (aChar == '_') +static XMLCat charCat(UChar character) +{ + if (character == '_') return NameStart; - if (aChar == '.' || aChar == '-') + if (character == '.' || character == '-') return NameCont; - CharCategory category = Unicode::category(aChar); - if (category & (Letter_Uppercase | Letter_Lowercase | Letter_Other | Letter_Titlecase | Number_Letter)) + unsigned characterTypeMask = U_GET_GC_MASK(character); + if (characterTypeMask & (U_GC_LU_MASK | U_GC_LL_MASK | U_GC_LO_MASK | U_GC_LT_MASK | U_GC_NL_MASK)) return NameStart; - if (category & (Mark_NonSpacing | Mark_SpacingCombining | Mark_Enclosing | Letter_Modifier | Number_DecimalDigit)) + if (characterTypeMask & (U_GC_M_MASK | U_GC_LM_MASK | U_GC_ND_MASK)) return NameCont; return NotPartOfName; } -static void setUpAxisNamesMap(AxisNamesMap& axisNames) +static void populateAxisNamesMap(HashMap<String, Step::Axis>& axisNames) { struct AxisName { const char* name; @@ -89,36 +99,23 @@ static void setUpAxisNamesMap(AxisNamesMap& axisNames) { "preceding-sibling", Step::PrecedingSiblingAxis }, { "self", Step::SelfAxis } }; - for (unsigned i = 0; i < sizeof(axisNameList) / sizeof(axisNameList[0]); ++i) - axisNames.set(axisNameList[i].name, axisNameList[i].axis); + for (auto& axisName : axisNameList) + axisNames.add(axisName.name, axisName.axis); } -static bool isAxisName(const String& name, Step::Axis& type) +static bool parseAxisName(const String& name, Step::Axis& type) { - DEFINE_STATIC_LOCAL(AxisNamesMap, axisNames, ()); + static NeverDestroyed<HashMap<String, Step::Axis>> axisNames; + if (axisNames.get().isEmpty()) + populateAxisNamesMap(axisNames); - if (axisNames.isEmpty()) - setUpAxisNamesMap(axisNames); - - AxisNamesMap::iterator it = axisNames.find(name); - if (it == axisNames.end()) + auto it = axisNames.get().find(name); + if (it == axisNames.get().end()) return false; type = it->value; return true; } -static bool isNodeTypeName(const String& name) -{ - DEFINE_STATIC_LOCAL(HashSet<String>, nodeTypeNames, ()); - if (nodeTypeNames.isEmpty()) { - nodeTypeNames.add("comment"); - nodeTypeNames.add("text"); - nodeTypeNames.add("processing-instruction"); - nodeTypeNames.add("node"); - } - return nodeTypeNames.contains(name); -} - // Returns whether the current token can possibly be a binary operator, given // the previous token. Necessary to disambiguate some of the operators // (* (multiply), div, and, or, mod) in the [32] Operator rule @@ -143,25 +140,25 @@ void Parser::skipWS() ++m_nextPos; } -Token Parser::makeTokenAndAdvance(int code, int advance) +Parser::Token Parser::makeTokenAndAdvance(int code, int advance) { m_nextPos += advance; return Token(code); } -Token Parser::makeTokenAndAdvance(int code, NumericOp::Opcode val, int advance) +Parser::Token Parser::makeTokenAndAdvance(int code, NumericOp::Opcode val, int advance) { m_nextPos += advance; return Token(code, val); } -Token Parser::makeTokenAndAdvance(int code, EqTestOp::Opcode val, int advance) +Parser::Token Parser::makeTokenAndAdvance(int code, EqTestOp::Opcode val, int advance) { m_nextPos += advance; return Token(code, val); } -// Returns next char if it's there and interesting, 0 otherwise +// Returns next char if it's there and interesting, 0 otherwise. char Parser::peekAheadHelper() { if (m_nextPos + 1 >= m_data.length()) @@ -182,7 +179,7 @@ char Parser::peekCurHelper() return next; } -Token Parser::lexString() +Parser::Token Parser::lexString() { UChar delimiter = m_data[m_nextPos]; int startPos = m_nextPos + 1; @@ -201,7 +198,7 @@ Token Parser::lexString() return Token(XPATH_ERROR); } -Token Parser::lexNumber() +Parser::Token Parser::lexNumber() { int startPos = m_nextPos; bool seenDot = false; @@ -263,7 +260,7 @@ bool Parser::lexQName(String& name) return true; } -Token Parser::nextTokenInternal() +inline Parser::Token Parser::nextTokenInternal() { skipWS(); @@ -351,7 +348,7 @@ Token Parser::nextTokenInternal() //It might be an axis name. Step::Axis axis; - if (isAxisName(name, axis)) + if (parseAxisName(name, axis)) return Token(AXISNAME, axis); // Ugh, :: is only valid in axis names -> error return Token(XPATH_ERROR); @@ -373,17 +370,21 @@ Token Parser::nextTokenInternal() } skipWS(); + if (peekCurHelper() == '(') { - //note: we don't swallow the (here! - - //either node type of function name - if (isNodeTypeName(name)) { - if (name == "processing-instruction") - return Token(PI, name); + // note: we don't swallow the '(' here! + + // Either node type oor function name. + + if (name == "processing-instruction") + return Token(PI); + if (name == "node") + return Token(NODE); + if (name == "text") + return Token(TEXT); + if (name == "comment") + return Token(COMMENT); - return Token(NODETYPE, name); - } - //must be a function name. return Token(FUNCTIONNAME, name); } @@ -391,239 +392,87 @@ Token Parser::nextTokenInternal() return Token(NAMETEST, name); } -Token Parser::nextToken() +inline Parser::Token Parser::nextToken() { - Token toRet = nextTokenInternal(); - m_lastTokenType = toRet.type; - return toRet; + Token token = nextTokenInternal(); + m_lastTokenType = token.type; + return token; } -Parser::Parser() +Parser::Parser(const String& statement, XPathNSResolver* resolver) + : m_data(statement) + , m_resolver(resolver) + , m_nextPos(0) + , m_lastTokenType(0) + , m_sawNamespaceError(false) { - reset(String()); } -Parser::~Parser() +int Parser::lex(YYSTYPE& yylval) { -} - -void Parser::reset(const String& data) -{ - m_nextPos = 0; - m_data = data; - m_lastTokenType = 0; - - m_topExpr = 0; - m_gotNamespaceError = false; -} + Token token = nextToken(); -int Parser::lex(void* data) -{ - YYSTYPE* yylval = static_cast<YYSTYPE*>(data); - Token tok = nextToken(); - - switch (tok.type) { + switch (token.type) { case AXISNAME: - yylval->axis = tok.axis; + yylval.axis = token.axis; break; case MULOP: - yylval->numop = tok.numop; + yylval.numericOpcode = token.numericOpcode; break; case RELOP: case EQOP: - yylval->eqop = tok.eqop; + yylval.equalityTestOpcode = token.equalityTestOpcode; break; case NODETYPE: - case PI: case FUNCTIONNAME: case LITERAL: case VARIABLEREFERENCE: case NUMBER: case NAMETEST: - yylval->str = new String(tok.str); - registerString(yylval->str); + yylval.string = token.string.releaseImpl().leakRef(); break; } - return tok.type; + return token.type; } -bool Parser::expandQName(const String& qName, String& localName, String& namespaceURI) +bool Parser::expandQualifiedName(const String& qualifiedName, String& localName, String& namespaceURI) { - size_t colon = qName.find(':'); + size_t colon = qualifiedName.find(':'); if (colon != notFound) { - if (!m_resolver) + if (!m_resolver) { + m_sawNamespaceError = true; return false; - namespaceURI = m_resolver->lookupNamespaceURI(qName.left(colon)); - if (namespaceURI.isNull()) + } + namespaceURI = m_resolver->lookupNamespaceURI(qualifiedName.left(colon)); + if (namespaceURI.isNull()) { + m_sawNamespaceError = true; return false; - localName = qName.substring(colon + 1); + } + localName = qualifiedName.substring(colon + 1); } else - localName = qName; - + localName = qualifiedName; + return true; } -Expression* Parser::parseStatement(const String& statement, PassRefPtr<XPathNSResolver> resolver, ExceptionCode& ec) +std::unique_ptr<Expression> Parser::parseStatement(const String& statement, XPathNSResolver* resolver, ExceptionCode& ec) { - reset(statement); - - m_resolver = resolver; - - Parser* oldParser = currentParser; - currentParser = this; - int parseError = xpathyyparse(this); - currentParser = oldParser; - - if (parseError) { - deleteAllValues(m_parseNodes); - m_parseNodes.clear(); - - HashSet<Vector<Predicate*>*>::iterator pend = m_predicateVectors.end(); - for (HashSet<Vector<Predicate*>*>::iterator it = m_predicateVectors.begin(); it != pend; ++it) { - deleteAllValues(**it); - delete *it; - } - m_predicateVectors.clear(); - - HashSet<Vector<Expression*>*>::iterator eend = m_expressionVectors.end(); - for (HashSet<Vector<Expression*>*>::iterator it = m_expressionVectors.begin(); it != eend; ++it) { - deleteAllValues(**it); - delete *it; - } - m_expressionVectors.clear(); - - deleteAllValues(m_strings); - m_strings.clear(); - - deleteAllValues(m_nodeTests); - m_nodeTests.clear(); + Parser parser(statement, resolver); - m_topExpr = 0; + int parseError = xpathyyparse(parser); - if (m_gotNamespaceError) - ec = NAMESPACE_ERR; - else - ec = XPathException::INVALID_EXPRESSION_ERR; - return 0; + if (parser.m_sawNamespaceError) { + ec = NAMESPACE_ERR; + return nullptr; } - ASSERT(m_parseNodes.size() == 1); - ASSERT(*m_parseNodes.begin() == m_topExpr); - ASSERT(m_expressionVectors.size() == 0); - ASSERT(m_predicateVectors.size() == 0); - ASSERT(m_strings.size() == 0); - ASSERT(m_nodeTests.size() == 0); - - m_parseNodes.clear(); - Expression* result = m_topExpr; - m_topExpr = 0; - - return result; -} - -void Parser::registerParseNode(ParseNode* node) -{ - if (node == 0) - return; - - ASSERT(!m_parseNodes.contains(node)); - - m_parseNodes.add(node); -} - -void Parser::unregisterParseNode(ParseNode* node) -{ - if (node == 0) - return; - - ASSERT(m_parseNodes.contains(node)); - - m_parseNodes.remove(node); -} - -void Parser::registerPredicateVector(Vector<Predicate*>* vector) -{ - if (vector == 0) - return; - - ASSERT(!m_predicateVectors.contains(vector)); - - m_predicateVectors.add(vector); -} - -void Parser::deletePredicateVector(Vector<Predicate*>* vector) -{ - if (vector == 0) - return; - - ASSERT(m_predicateVectors.contains(vector)); - - m_predicateVectors.remove(vector); - delete vector; -} - - -void Parser::registerExpressionVector(Vector<Expression*>* vector) -{ - if (vector == 0) - return; - - ASSERT(!m_expressionVectors.contains(vector)); - - m_expressionVectors.add(vector); -} - -void Parser::deleteExpressionVector(Vector<Expression*>* vector) -{ - if (vector == 0) - return; - - ASSERT(m_expressionVectors.contains(vector)); - - m_expressionVectors.remove(vector); - delete vector; -} - -void Parser::registerString(String* s) -{ - if (s == 0) - return; - - ASSERT(!m_strings.contains(s)); - - m_strings.add(s); -} - -void Parser::deleteString(String* s) -{ - if (s == 0) - return; - - ASSERT(m_strings.contains(s)); - - m_strings.remove(s); - delete s; -} - -void Parser::registerNodeTest(Step::NodeTest* t) -{ - if (t == 0) - return; - - ASSERT(!m_nodeTests.contains(t)); - - m_nodeTests.add(t); -} + if (parseError) { + ec = XPathException::INVALID_EXPRESSION_ERR; + return nullptr; + } -void Parser::deleteNodeTest(Step::NodeTest* t) -{ - if (t == 0) - return; - - ASSERT(m_nodeTests.contains(t)); - - m_nodeTests.remove(t); - delete t; + return WTFMove(parser.m_result); } +} } |