| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // Class header file. |
| #include "XPath.hpp" |
| |
| |
| |
| #include <cassert> |
| #include <cfloat> |
| |
| |
| |
| #include <xalanc/Include/STLHelper.hpp> |
| |
| |
| |
| #include <xalanc/XalanDOM/XalanNamedNodeMap.hpp> |
| |
| |
| |
| #include <xalanc/PlatformSupport/DoubleSupport.hpp> |
| #include <xalanc/PlatformSupport/XalanMessageLoader.hpp> |
| #include <xalanc/PlatformSupport/PrefixResolver.hpp> |
| |
| |
| |
| #include <xalanc/DOMSupport/DOMServices.hpp> |
| |
| |
| |
| #include "FormatterStringLengthCounter.hpp" |
| #include "MutableNodeRefList.hpp" |
| #include "XalanQNameByReference.hpp" |
| #include "XObject.hpp" |
| #include "XObjectFactory.hpp" |
| #include "XPathConstructionContext.hpp" |
| #include "XPathEnvSupport.hpp" |
| |
| |
| |
| namespace XALAN_CPP_NAMESPACE { |
| |
| |
| |
| |
| const XalanDOMString XPath::s_emptyString(XalanMemMgrs::getDummyMemMgr()); |
| |
| |
| |
| XPath::XPath( |
| MemoryManager& theManager, |
| const Locator* theLocator) : |
| m_expression(theManager), |
| m_locator(theLocator), |
| m_inStylesheet(false) |
| { |
| } |
| |
| |
| |
| XPath* |
| XPath::create( |
| MemoryManager& theManager, |
| const Locator* theLocator) |
| { |
| typedef XPath ThisType; |
| |
| XalanAllocationGuard theGuard(theManager, theManager.allocate(sizeof(ThisType))); |
| |
| ThisType* const theResult = |
| new (theGuard.get()) ThisType( |
| theManager, |
| theLocator); |
| |
| theGuard.release(); |
| |
| return theResult; |
| } |
| |
| |
| |
| XPath::~XPath() |
| { |
| } |
| |
| |
| |
| void |
| XPath::unknownOpCodeError( |
| XalanNode* context, |
| XPathExecutionContext& executionContext, |
| OpCodeMapPositionType opPos) const |
| { |
| const GetCachedString theGuard1(executionContext); |
| |
| XalanDOMString& theOpCode = theGuard1.get(); |
| |
| NumberToDOMString( |
| m_expression.getOpCodeMapValue(opPos), |
| theOpCode); |
| |
| const GetCachedString theGuard2(executionContext); |
| |
| executionContext.problem( |
| XPathExecutionContext::eXPath, |
| XPathExecutionContext::eError, |
| XalanMessageLoader::getMessage( |
| theGuard2.get(), |
| XalanMessages::InvalidOpcodeWasDetected_1Param, |
| theOpCode), |
| m_locator, |
| context); |
| } |
| |
| |
| |
| void |
| XPath::notNodeSetError( |
| XalanNode* context, |
| XPathExecutionContext& executionContext) const |
| { |
| GetCachedString theGuard(executionContext); |
| |
| XalanDOMString& theBuffer = theGuard.get(); |
| |
| executionContext.problem( |
| XPathExecutionContext::eXPath, |
| XPathExecutionContext::eError, |
| XalanMessageLoader::getMessage( |
| theBuffer, |
| XalanMessages::ExpressionDoesNotEvaluateToNodeSet), |
| m_locator, |
| context); |
| } |
| |
| |
| |
| const XObjectPtr |
| XPath::execute( |
| XalanNode* context, |
| const PrefixResolver& prefixResolver, |
| XPathExecutionContext& executionContext) const |
| { |
| // Push and pop the PrefixResolver... |
| const PrefixResolverSetAndRestore theResolverSetAndRestore( |
| executionContext, |
| &prefixResolver); |
| |
| // Push and pop the current node... |
| const CurrentNodePushAndPop theNodePushAndPop( |
| executionContext, |
| context); |
| |
| return executeMore( |
| context, |
| getInitialOpCodePosition(), |
| executionContext); |
| } |
| |
| |
| |
| void |
| XPath::execute( |
| XalanNode* context, |
| const PrefixResolver& prefixResolver, |
| XPathExecutionContext& executionContext, |
| bool& result) const |
| { |
| assert(context != 0); |
| |
| // Push and pop the PrefixResolver... |
| const PrefixResolverSetAndRestore theResolverSetAndRestore( |
| executionContext, |
| &prefixResolver); |
| |
| // Push and pop the current node... |
| const CurrentNodePushAndPop theNodePushAndPop( |
| executionContext, |
| context); |
| |
| executeMore( |
| context, |
| getInitialOpCodePosition(), |
| executionContext, |
| result); |
| } |
| |
| |
| |
| void |
| XPath::execute( |
| XalanNode* context, |
| const PrefixResolver& prefixResolver, |
| XPathExecutionContext& executionContext, |
| double& result) const |
| { |
| assert(context != 0); |
| |
| // Push and pop the PrefixResolver... |
| const PrefixResolverSetAndRestore theResolverSetAndRestore( |
| executionContext, |
| &prefixResolver); |
| |
| // Push and pop the current node... |
| const CurrentNodePushAndPop theNodePushAndPop( |
| executionContext, |
| context); |
| |
| executeMore( |
| context, |
| getInitialOpCodePosition(), |
| executionContext, |
| result); |
| } |
| |
| |
| |
| void |
| XPath::execute( |
| XalanNode* context, |
| const PrefixResolver& prefixResolver, |
| XPathExecutionContext& executionContext, |
| XalanDOMString& result) const |
| { |
| assert(context != 0); |
| |
| // Push and pop the PrefixResolver... |
| const PrefixResolverSetAndRestore theResolverSetAndRestore( |
| executionContext, |
| &prefixResolver); |
| |
| // Push and pop the current node... |
| const CurrentNodePushAndPop theNodePushAndPop( |
| executionContext, |
| context); |
| |
| executeMore( |
| context, |
| getInitialOpCodePosition(), |
| executionContext, |
| result); |
| } |
| |
| |
| |
| void |
| XPath::execute( |
| XalanNode* context, |
| const PrefixResolver& prefixResolver, |
| XPathExecutionContext& executionContext, |
| FormatterListener& formatterListener, |
| MemberFunctionPtr function) const |
| { |
| assert(context != 0); |
| |
| // Push and pop the PrefixResolver... |
| const PrefixResolverSetAndRestore theResolverSetAndRestore( |
| executionContext, |
| &prefixResolver); |
| |
| // Push and pop the current node... |
| const CurrentNodePushAndPop theNodePushAndPop( |
| executionContext, |
| context); |
| |
| executeMore( |
| context, |
| getInitialOpCodePosition(), |
| executionContext, |
| formatterListener, |
| function); |
| } |
| |
| |
| |
| const XObjectPtr |
| XPath::execute( |
| XalanNode* context, |
| const PrefixResolver& prefixResolver, |
| XPathExecutionContext& executionContext, |
| MutableNodeRefList& result) const |
| { |
| assert(context != 0); |
| assert(result.empty() == true); |
| |
| // Push and pop the PrefixResolver... |
| const PrefixResolverSetAndRestore theResolverSetAndRestore( |
| executionContext, |
| &prefixResolver); |
| |
| // Push and pop the current node... |
| const CurrentNodePushAndPop theNodePushAndPop( |
| executionContext, |
| context); |
| |
| return executeMore( |
| context, |
| getInitialOpCodePosition(), |
| executionContext, |
| result); |
| } |
| |
| |
| |
| const XObjectPtr |
| XPath::executeMore( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| switch(m_expression.getOpCodeMapValue(opPos)) |
| { |
| case XPathExpression::eOP_OR: |
| return executionContext.getXObjectFactory().createBoolean(Or(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_AND: |
| return executionContext.getXObjectFactory().createBoolean(And(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_NOTEQUALS: |
| return executionContext.getXObjectFactory().createBoolean(notequals(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_EQUALS: |
| return executionContext.getXObjectFactory().createBoolean(equals(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_LTE: |
| return executionContext.getXObjectFactory().createBoolean(lte(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_LT: |
| return executionContext.getXObjectFactory().createBoolean(lt(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_GTE: |
| return executionContext.getXObjectFactory().createBoolean(gte(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_GT: |
| return executionContext.getXObjectFactory().createBoolean(gt(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_PLUS: |
| return executionContext.getXObjectFactory().createNumber(plus(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_MINUS: |
| return executionContext.getXObjectFactory().createNumber(minus(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_MULT: |
| return executionContext.getXObjectFactory().createNumber(mult(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_DIV: |
| return executionContext.getXObjectFactory().createNumber(div(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_MOD: |
| return executionContext.getXObjectFactory().createNumber(mod(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_NEG: |
| return executionContext.getXObjectFactory().createNumber(neg(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_UNION: |
| return Union(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_LITERAL: |
| return literal(opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_VARIABLE: |
| return variable(opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_GROUP: |
| return group(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_NUMBERLIT: |
| return numberlit(opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_EXTFUNCTION: |
| return runExtFunction(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION: |
| return runFunction(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_LOCATIONPATH: |
| return locationPath(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_POSITION: |
| return executionContext.getXObjectFactory().createNumber(functionPosition(context, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LAST: |
| return executionContext.getXObjectFactory().createNumber(functionLast(executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_COUNT: |
| return executionContext.getXObjectFactory().createNumber(functionCount(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NOT: |
| return executionContext.getXObjectFactory().createBoolean(functionNot(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_TRUE: |
| return executionContext.getXObjectFactory().createBoolean(true); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_FALSE: |
| return executionContext.getXObjectFactory().createBoolean(false); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_BOOLEAN: |
| return executionContext.getXObjectFactory().createBoolean(functionBoolean(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NAME_0: |
| return executionContext.getXObjectFactory().createStringReference(functionName(context)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NAME_1: |
| return executionContext.getXObjectFactory().createStringReference(functionName(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LOCALNAME_0: |
| return executionContext.getXObjectFactory().createStringReference(functionLocalName(context)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LOCALNAME_1: |
| return executionContext.getXObjectFactory().createStringReference(functionLocalName(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_FLOOR: |
| return executionContext.getXObjectFactory().createNumber(functionFloor(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_CEILING: |
| return executionContext.getXObjectFactory().createNumber(functionCeiling(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_ROUND: |
| return executionContext.getXObjectFactory().createNumber(functionRound(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NUMBER_0: |
| return executionContext.getXObjectFactory().createNumber(functionNumber(context, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NUMBER_1: |
| return executionContext.getXObjectFactory().createNumber(functionNumber(context, opPos, executionContext)); |
| break; |
| |
| // case XPathExpression::eOP_FUNCTION_STRING_0: |
| // return functionString(context); |
| // break; |
| |
| // case XPathExpression::eOP_FUNCTION_STRING_1: |
| // return functionString(context, opPos, executionContext); |
| // break; |
| |
| case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0: |
| return executionContext.getXObjectFactory().createNumber(functionStringLength(context, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1: |
| return executionContext.getXObjectFactory().createNumber(functionStringLength(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_SUM: |
| return executionContext.getXObjectFactory().createNumber(functionSum(context, opPos, executionContext)); |
| break; |
| |
| default: |
| unknownOpCodeError(context, executionContext, opPos); |
| break; |
| } |
| |
| return XObjectPtr(); |
| } |
| |
| |
| |
| void |
| XPath::executeMore( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| bool& result) const |
| { |
| switch(m_expression.getOpCodeMapValue(opPos)) |
| { |
| case XPathExpression::eOP_OR: |
| result = Or(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_AND: |
| result = And(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_NOTEQUALS: |
| result = notequals(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_EQUALS: |
| result = equals(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_LTE: |
| result = lte(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_LT: |
| result = lt(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_GTE: |
| result = gte(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_GT: |
| result = gt(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_PLUS: |
| result = XObject::boolean(plus(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_MINUS: |
| result = XObject::boolean(minus(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_MULT: |
| result = XObject::boolean(mult(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_DIV: |
| result = XObject::boolean(div(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_MOD: |
| result = XObject::boolean(mod(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_NEG: |
| result = XObject::boolean(neg(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_UNION: |
| Union(context, opPos, executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_LITERAL: |
| literal(opPos, result); |
| break; |
| |
| case XPathExpression::eOP_VARIABLE: |
| result = variable(opPos, executionContext)->boolean(executionContext); |
| break; |
| |
| case XPathExpression::eOP_GROUP: |
| group(context, opPos, executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_NUMBERLIT: |
| numberlit(opPos, result); |
| break; |
| |
| case XPathExpression::eOP_EXTFUNCTION: |
| result = runExtFunction(context, opPos, executionContext)->boolean(executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION: |
| result = runFunction(context, opPos, executionContext)->boolean(executionContext); |
| break; |
| |
| case XPathExpression::eOP_LOCATIONPATH: |
| locationPath(context, opPos, executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_POSITION: |
| result = XObject::boolean(functionPosition(context, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LAST: |
| result = XObject::boolean(functionLast(executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_COUNT: |
| result = XObject::boolean(functionCount(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NOT: |
| result = functionNot(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_TRUE: |
| result = true; |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_FALSE: |
| result = false; |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_BOOLEAN: |
| result = functionBoolean(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NAME_0: |
| result = XObject::boolean(functionName(context)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NAME_1: |
| result = XObject::boolean(functionName(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LOCALNAME_0: |
| result = XObject::boolean(functionLocalName(context)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LOCALNAME_1: |
| result = XObject::boolean(functionLocalName(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_FLOOR: |
| result = XObject::boolean(functionFloor(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_CEILING: |
| result = XObject::boolean(functionCeiling(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_ROUND: |
| result = XObject::boolean(functionRound(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NUMBER_0: |
| result = XObject::boolean(functionNumber(context, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NUMBER_1: |
| result = XObject::boolean(functionNumber(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0: |
| result = XObject::boolean(functionStringLength(context, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1: |
| result = XObject::boolean(functionStringLength(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_SUM: |
| result = XObject::boolean(functionSum(context, opPos, executionContext)); |
| break; |
| |
| default: |
| unknownOpCodeError(context, executionContext, opPos); |
| break; |
| } |
| } |
| |
| |
| |
| void |
| XPath::executeMore( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| double& result) const |
| { |
| switch(m_expression.getOpCodeMapValue(opPos)) |
| { |
| case XPathExpression::eOP_OR: |
| result = XObject::number(Or(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_AND: |
| result = XObject::number(And(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_NOTEQUALS: |
| result = XObject::number(notequals(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_EQUALS: |
| result = XObject::number(equals(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_LTE: |
| result = XObject::number(lte(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_LT: |
| result = XObject::number(lt(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_GTE: |
| result = XObject::number(gte(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_GT: |
| result = XObject::number(gt(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_PLUS: |
| result = plus(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_MINUS: |
| result = minus(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_MULT: |
| result = mult(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_DIV: |
| result = div(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_MOD: |
| result = mod(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_NEG: |
| result = neg(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_UNION: |
| Union(context, opPos, executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_LITERAL: |
| literal(opPos, result); |
| break; |
| |
| case XPathExpression::eOP_VARIABLE: |
| result = variable(opPos, executionContext)->num(executionContext); |
| break; |
| |
| case XPathExpression::eOP_GROUP: |
| group(context, opPos, executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_NUMBERLIT: |
| result = numberlit(opPos); |
| break; |
| |
| case XPathExpression::eOP_EXTFUNCTION: |
| result = runExtFunction(context, opPos, executionContext)->num(executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION: |
| result = runFunction(context, opPos, executionContext)->num(executionContext); |
| break; |
| |
| case XPathExpression::eOP_LOCATIONPATH: |
| locationPath(context, opPos, executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_POSITION: |
| result = functionPosition(context, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LAST: |
| result = functionLast(executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_COUNT: |
| result = functionCount(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NOT: |
| result = XObject::number(functionNot(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_TRUE: |
| result = XObject::number(true); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_FALSE: |
| result = XObject::number(false); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_BOOLEAN: |
| result = XObject::number(functionBoolean(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NAME_0: |
| result = XObject::number(functionName(context),executionContext.getMemoryManager()); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NAME_1: |
| result = XObject::number(functionName(context, opPos, executionContext),executionContext.getMemoryManager()); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LOCALNAME_0: |
| result = XObject::number(functionLocalName(context),executionContext.getMemoryManager()); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LOCALNAME_1: |
| result = XObject::number(functionLocalName(context, opPos, executionContext),executionContext.getMemoryManager()); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_FLOOR: |
| result = functionFloor(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_CEILING: |
| result = functionCeiling(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_ROUND: |
| result = functionRound(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NUMBER_0: |
| result = functionNumber(context, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NUMBER_1: |
| result = functionNumber(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0: |
| result = functionStringLength(context, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1: |
| result = functionStringLength(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_SUM: |
| result = functionSum(context, opPos, executionContext); |
| break; |
| |
| default: |
| unknownOpCodeError(context, executionContext, opPos); |
| break; |
| } |
| } |
| |
| |
| |
| void |
| XPath::executeMore( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| XalanDOMString& result) const |
| { |
| switch(m_expression.getOpCodeMapValue(opPos)) |
| { |
| case XPathExpression::eOP_OR: |
| XObject::string(Or(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_AND: |
| XObject::string(And(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_NOTEQUALS: |
| XObject::string(notequals(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_EQUALS: |
| XObject::string(equals(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_LTE: |
| XObject::string(lte(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_LT: |
| XObject::string(lt(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_GTE: |
| XObject::string(gte(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_GT: |
| XObject::string(gt(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_PLUS: |
| XObject::string(plus(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_MINUS: |
| XObject::string(minus(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_MULT: |
| XObject::string(mult(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_DIV: |
| XObject::string(div(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_MOD: |
| XObject::string(mod(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_NEG: |
| XObject::string(neg(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_UNION: |
| Union(context, opPos, executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_LITERAL: |
| literal(opPos, result); |
| break; |
| |
| case XPathExpression::eOP_VARIABLE: |
| variable(opPos, executionContext)->str(executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_GROUP: |
| group(context, opPos, executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_NUMBERLIT: |
| numberlit(opPos, result); |
| break; |
| |
| case XPathExpression::eOP_EXTFUNCTION: |
| runExtFunction(context, opPos, executionContext)->str(executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION: |
| runFunction(context, opPos, executionContext)->str(executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_LOCATIONPATH: |
| locationPath(context, opPos, executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_POSITION: |
| XObject::string(functionPosition(context, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LAST: |
| XObject::string(functionLast(executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_COUNT: |
| XObject::string(functionCount(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NOT: |
| XObject::string(functionNot(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_TRUE: |
| XObject::string(true, result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_FALSE: |
| XObject::string(false, result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_BOOLEAN: |
| XObject::string(functionBoolean(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NAME_0: |
| result.append(functionName(context)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NAME_1: |
| result.append(functionName(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LOCALNAME_0: |
| result.append(functionLocalName(context)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LOCALNAME_1: |
| result.append(functionLocalName(context, opPos, executionContext)); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_FLOOR: |
| XObject::string(functionFloor(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_CEILING: |
| XObject::string(functionCeiling(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_ROUND: |
| XObject::string(functionRound(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NUMBER_0: |
| XObject::string(functionNumber(context, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NUMBER_1: |
| XObject::string(functionNumber(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0: |
| XObject::string(functionStringLength(context, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1: |
| XObject::string(functionStringLength(context, opPos, executionContext), result); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_SUM: |
| XObject::string(functionSum(context, opPos, executionContext), result); |
| break; |
| |
| default: |
| unknownOpCodeError(context, executionContext, opPos); |
| break; |
| } |
| } |
| |
| |
| |
| inline void |
| stringToCharacters( |
| const XalanDOMString& str, |
| FormatterListener& formatterListener, |
| XPath::MemberFunctionPtr function) |
| { |
| const XalanDOMString::size_type theLength = str.length(); |
| |
| if (theLength != 0) |
| { |
| assert(theLength == FormatterListener::size_type(theLength)); |
| |
| (formatterListener.*function)( |
| str.c_str(), |
| FormatterListener::size_type(theLength)); |
| } |
| } |
| |
| |
| |
| void |
| XPath::executeMore( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| FormatterListener& formatterListener, |
| MemberFunctionPtr function) const |
| { |
| switch(m_expression.getOpCodeMapValue(opPos)) |
| { |
| case XPathExpression::eOP_OR: |
| XObject::string( |
| Or(context, opPos, executionContext), |
| formatterListener, |
| function); |
| break; |
| |
| case XPathExpression::eOP_AND: |
| XObject::string( |
| And(context, opPos, executionContext), |
| formatterListener, |
| function); |
| break; |
| |
| case XPathExpression::eOP_NOTEQUALS: |
| XObject::string( |
| notequals(context, opPos, executionContext), |
| formatterListener, |
| function); |
| break; |
| |
| case XPathExpression::eOP_EQUALS: |
| XObject::string( |
| equals(context, opPos, executionContext), |
| formatterListener, |
| function); |
| break; |
| |
| case XPathExpression::eOP_LTE: |
| XObject::string( |
| lte(context, opPos, executionContext), |
| formatterListener, |
| function); |
| break; |
| |
| case XPathExpression::eOP_LT: |
| XObject::string( |
| lt(context, opPos, executionContext), |
| formatterListener, |
| function); |
| break; |
| |
| case XPathExpression::eOP_GTE: |
| XObject::string( |
| gte(context, opPos, executionContext), |
| formatterListener, |
| function); |
| break; |
| |
| case XPathExpression::eOP_GT: |
| XObject::string( |
| gt(context, opPos, executionContext), |
| formatterListener, |
| function); |
| break; |
| |
| case XPathExpression::eOP_PLUS: |
| plus(context, opPos, executionContext, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_MINUS: |
| minus(context, opPos, executionContext, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_MULT: |
| mult(context, opPos, executionContext, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_DIV: |
| div(context, opPos, executionContext, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_MOD: |
| mod(context, opPos, executionContext, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_NEG: |
| neg(context, opPos, executionContext, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_UNION: |
| Union(context, opPos, executionContext, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_LITERAL: |
| literal(opPos, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_VARIABLE: |
| variable(opPos, executionContext)->str(executionContext, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_GROUP: |
| group(context, opPos, executionContext, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_NUMBERLIT: |
| numberlit(opPos, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_EXTFUNCTION: |
| runExtFunction(context, opPos, executionContext)->str(executionContext, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION: |
| runFunction(context, opPos, executionContext)->str(executionContext, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_LOCATIONPATH: |
| locationPath(context, opPos, executionContext, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_POSITION: |
| XObject::string(functionPosition(context, executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LAST: |
| XObject::string(functionLast(executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_COUNT: |
| XObject::string(functionCount(context, opPos, executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NOT: |
| XObject::string(functionNot(context, opPos, executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_TRUE: |
| XObject::string(true, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_FALSE: |
| XObject::string(false, formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_BOOLEAN: |
| XObject::string(functionBoolean(context, opPos, executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NAME_0: |
| stringToCharacters(functionName(context), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NAME_1: |
| stringToCharacters(functionName(context, opPos, executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LOCALNAME_0: |
| stringToCharacters(functionLocalName(context), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_LOCALNAME_1: |
| stringToCharacters(functionLocalName(context, opPos, executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_FLOOR: |
| XObject::string(functionFloor(context, opPos, executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_CEILING: |
| XObject::string(functionCeiling(context, opPos, executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_ROUND: |
| XObject::string(functionRound(context, opPos, executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NUMBER_0: |
| XObject::string(functionNumber(context, executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_NUMBER_1: |
| XObject::string(functionNumber(context, opPos, executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0: |
| XObject::string(functionStringLength(context, executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1: |
| XObject::string(functionStringLength(context, opPos, executionContext), formatterListener, function); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION_SUM: |
| XObject::string(functionSum(context, opPos, executionContext), formatterListener, function); |
| break; |
| |
| default: |
| unknownOpCodeError(context, executionContext, opPos); |
| break; |
| } |
| } |
| |
| |
| |
| const XObjectPtr |
| XPath::executeMore( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| MutableNodeRefList& result) const |
| { |
| XObjectPtr theXObject; |
| |
| switch(m_expression.getOpCodeMapValue(opPos)) |
| { |
| case XPathExpression::eOP_XPATH: |
| theXObject = executeMore(context, opPos + 2, executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_OR: |
| case XPathExpression::eOP_AND: |
| case XPathExpression::eOP_NOTEQUALS: |
| case XPathExpression::eOP_EQUALS: |
| case XPathExpression::eOP_LTE: |
| case XPathExpression::eOP_LT: |
| case XPathExpression::eOP_GTE: |
| case XPathExpression::eOP_GT: |
| case XPathExpression::eOP_PLUS: |
| case XPathExpression::eOP_MINUS: |
| case XPathExpression::eOP_MULT: |
| case XPathExpression::eOP_DIV: |
| case XPathExpression::eOP_MOD: |
| case XPathExpression::eOP_NEG: |
| case XPathExpression::eOP_LITERAL: |
| case XPathExpression::eOP_NUMBERLIT: |
| case XPathExpression::eOP_FUNCTION_POSITION: |
| case XPathExpression::eOP_FUNCTION_LAST: |
| case XPathExpression::eOP_FUNCTION_COUNT: |
| case XPathExpression::eOP_FUNCTION_NOT: |
| case XPathExpression::eOP_FUNCTION_TRUE: |
| case XPathExpression::eOP_FUNCTION_FALSE: |
| case XPathExpression::eOP_FUNCTION_BOOLEAN: |
| case XPathExpression::eOP_FUNCTION_NAME_0: |
| case XPathExpression::eOP_FUNCTION_NAME_1: |
| case XPathExpression::eOP_FUNCTION_LOCALNAME_0: |
| case XPathExpression::eOP_FUNCTION_LOCALNAME_1: |
| case XPathExpression::eOP_FUNCTION_FLOOR: |
| case XPathExpression::eOP_FUNCTION_CEILING: |
| case XPathExpression::eOP_FUNCTION_ROUND: |
| case XPathExpression::eOP_FUNCTION_NUMBER_0: |
| case XPathExpression::eOP_FUNCTION_NUMBER_1: |
| case XPathExpression::eOP_FUNCTION_STRING_0: |
| case XPathExpression::eOP_FUNCTION_STRING_1: |
| case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0: |
| case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1: |
| case XPathExpression::eOP_FUNCTION_NAMESPACEURI_0: |
| case XPathExpression::eOP_FUNCTION_NAMESPACEURI_1: |
| case XPathExpression::eOP_FUNCTION_SUM: |
| notNodeSetError(context, executionContext); |
| break; |
| |
| case XPathExpression::eOP_UNION: |
| Union(context, opPos, executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_VARIABLE: |
| theXObject = variable(opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_GROUP: |
| group(context, opPos, executionContext, result); |
| break; |
| |
| case XPathExpression::eOP_EXTFUNCTION: |
| theXObject = runExtFunction(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_FUNCTION: |
| theXObject = runFunction(context, opPos, executionContext); |
| break; |
| |
| case XPathExpression::eOP_LOCATIONPATH: |
| locationPath(context, opPos, executionContext, result); |
| break; |
| |
| default: |
| unknownOpCodeError(context, executionContext, opPos); |
| break; |
| } |
| |
| if (theXObject.null() == false && theXObject->getType() != XObject::eTypeNodeSet) |
| { |
| notNodeSetError(context, executionContext); |
| } |
| |
| return theXObject; |
| } |
| |
| |
| |
| inline void |
| XPath::doGetMatchScore( |
| XalanNode* context, |
| XPathExecutionContext& executionContext, |
| eMatchScore& score) const |
| { |
| assert(context != 0); |
| |
| OpCodeMapPositionType opPos = |
| m_expression.getInitialOpCodePosition() + 2; |
| |
| while(m_expression.getOpCodeMapValue(opPos) == XPathExpression::eOP_LOCATIONPATHPATTERN) |
| { |
| const OpCodeMapPositionType nextOpPos = m_expression.getNextOpCodePosition(opPos); |
| |
| score = locationPathPattern(executionContext, *context, opPos); |
| |
| if(score == eMatchScoreNone) |
| { |
| opPos = nextOpPos; |
| } |
| else |
| { |
| break; |
| } |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::getMatchScore( |
| XalanNode* node, |
| XPathExecutionContext& executionContext) const |
| { |
| eMatchScore score = eMatchScoreNone; |
| |
| if(m_expression.getOpCodeMapValue(0) != XPathExpression::eOP_MATCHPATTERN) |
| { |
| GetCachedString theGuard(executionContext); |
| |
| XalanDOMString& theBuffer = theGuard.get(); |
| |
| executionContext.problem( |
| XPathExecutionContext::eXPath, |
| XPathExecutionContext::eError, |
| XalanMessageLoader::getMessage( |
| theBuffer, |
| XalanMessages::CannotEvaluateXPathExpressionAsMatchPattern), |
| m_locator, |
| node); |
| } |
| else |
| { |
| assert(node != 0); |
| |
| doGetMatchScore(node, executionContext, score); |
| } |
| |
| return score; |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::getMatchScore( |
| XalanNode* node, |
| const PrefixResolver& resolver, |
| XPathExecutionContext& executionContext) const |
| { |
| const PrefixResolver* const theCurrentResolver = |
| executionContext.getPrefixResolver(); |
| |
| if (theCurrentResolver == &resolver) |
| { |
| return getMatchScore(node, executionContext); |
| } |
| else |
| { |
| // Push and pop the PrefixResolver... |
| const PrefixResolverSetAndRestore theSetAndRestore( |
| executionContext, |
| theCurrentResolver, |
| &resolver); |
| |
| return getMatchScore(node, executionContext); |
| } |
| } |
| |
| |
| |
| inline const XalanDOMString* |
| getStringFromTokenQueue( |
| const XPathExpression& expression, |
| XPath::OpCodeMapPositionType opPos) |
| { |
| const XPath::OpCodeMapValueType tokenPosition = |
| expression.getOpCodeMapValue(opPos); |
| |
| if (tokenPosition == XPathExpression::eEMPTY || |
| tokenPosition == XPathExpression::eELEMWILDCARD) |
| { |
| return 0; |
| } |
| else |
| { |
| assert(tokenPosition != XPathExpression::eENDOP); |
| |
| const XToken* const token = |
| expression.getToken(tokenPosition); |
| assert(token != 0); |
| |
| return &token->str(); |
| } |
| } |
| |
| |
| |
| void |
| XPath::getTargetData(TargetDataVectorType& targetData) const |
| { |
| OpCodeMapPositionType opPos = |
| m_expression.getInitialOpCodePosition() + 2; |
| |
| targetData.reserve(eDefaultTargetDataSize); |
| |
| while(m_expression.getOpCodeMapValue(opPos) == XPathExpression::eOP_LOCATIONPATHPATTERN) |
| { |
| const OpCodeMapPositionType nextOpPos = m_expression.getNextOpCodePosition(opPos); |
| |
| opPos += 2; |
| |
| unsigned long stepCount = 0; |
| |
| while(m_expression.getOpCodeMapValue(opPos) != XPathExpression::eENDOP) |
| { |
| ++stepCount; |
| |
| const OpCodeMapPositionType nextStepPos = |
| m_expression.getNextOpCodePosition(opPos); |
| |
| const OpCodeMapValueType nextOp = m_expression.getOpCodeMapValue(nextStepPos); |
| |
| if(nextOp == XPathExpression::eENDOP) |
| { |
| eMatchScore score = eMatchScoreNone; |
| |
| const XalanDOMChar* targetLocalName = 0; |
| |
| TargetData::eTargetType targetType = TargetData::eOther; |
| |
| bool fIsAttribute = false; |
| |
| const OpCodeMapValueType stepType = m_expression.getOpCodeMapValue(opPos); |
| |
| opPos += 3; |
| |
| switch(stepType) |
| { |
| case XPathExpression::eOP_FUNCTION: |
| targetLocalName = PSEUDONAME_ANY; |
| score = eMatchScoreOther; |
| targetType = TargetData::eAny; |
| break; |
| |
| case XPathExpression::eFROM_ROOT: |
| targetLocalName = PSEUDONAME_ROOT; |
| score = eMatchScoreOther; |
| break; |
| |
| case XPathExpression::eMATCH_ATTRIBUTE: |
| fIsAttribute = true; |
| // fall through on purpose... |
| |
| case XPathExpression::eMATCH_ANY_ANCESTOR: |
| case XPathExpression::eMATCH_IMMEDIATE_ANCESTOR: |
| { |
| const OpCodeMapValueType tok = m_expression.getOpCodeMapValue(opPos); |
| |
| switch(tok) |
| { |
| case XPathExpression::eNODETYPE_COMMENT: |
| targetLocalName = PSEUDONAME_COMMENT; |
| score = eMatchScoreNodeTest; |
| break; |
| |
| case XPathExpression::eNODETYPE_TEXT: |
| targetLocalName = PSEUDONAME_TEXT; |
| score = eMatchScoreNodeTest; |
| break; |
| |
| case XPathExpression::eNODETYPE_NODE: |
| targetLocalName = PSEUDONAME_NODE; |
| score = eMatchScoreNodeTest; |
| break; |
| |
| case XPathExpression::eNODETYPE_ROOT: |
| targetLocalName = PSEUDONAME_ROOT; |
| score = eMatchScoreNodeTest; |
| break; |
| |
| case XPathExpression::eNODETYPE_ANYELEMENT: |
| targetLocalName = PSEUDONAME_ANY; |
| score = eMatchScoreNodeTest; |
| targetType = TargetData::eElement; |
| break; |
| |
| case XPathExpression::eNODETYPE_PI: |
| { |
| const OpCodeMapValueType argLen = |
| m_expression.getOpCodeArgumentLength(opPos - 3); |
| |
| targetLocalName = PSEUDONAME_PI; |
| |
| if (argLen == 1) |
| { |
| score = eMatchScoreNodeTest; |
| } |
| else if (argLen == 2) |
| { |
| score = eMatchScoreQName; |
| } |
| } |
| break; |
| |
| case XPathExpression::eNODENAME: |
| { |
| const XalanDOMString* const targetNamespace = |
| getStringFromTokenQueue(m_expression, opPos + 1); |
| |
| const XalanDOMString* const targetLocal = |
| getStringFromTokenQueue(m_expression, opPos + 2); |
| |
| if (targetLocal == 0) |
| { |
| targetLocalName = 0; |
| } |
| else |
| { |
| targetLocalName = targetLocal->c_str(); |
| } |
| |
| targetType = fIsAttribute ? |
| TargetData::eAttribute : |
| TargetData::eElement; |
| |
| if(targetLocalName != 0) |
| { |
| if(targetLocalName == PSEUDONAME_ANY) |
| { |
| targetLocalName = PSEUDONAME_ANY; |
| |
| if (targetNamespace == 0 || |
| *targetNamespace == PSEUDONAME_ANY) |
| { |
| score = eMatchScoreNodeTest; |
| } |
| else |
| { |
| score = eMatchScoreNSWild; |
| } |
| } |
| else |
| { |
| score = eMatchScoreQName; |
| } |
| } |
| else |
| { |
| targetLocalName = PSEUDONAME_ANY; |
| |
| if (targetNamespace == 0 || |
| *targetNamespace == PSEUDONAME_ANY) |
| { |
| score = eMatchScoreNodeTest; |
| } |
| else |
| { |
| score = eMatchScoreNSWild; |
| } |
| } |
| } |
| |
| break; |
| |
| default: |
| targetLocalName = PSEUDONAME_ANY; |
| score = eMatchScoreNodeTest; |
| break; |
| } |
| } |
| break; |
| } |
| |
| assert(targetLocalName != 0); |
| |
| // If there are multiple steps, or a predicate, |
| // the priority is always eMatchScoreOther. |
| if (stepCount > 1 || |
| opPos + 3 < nextStepPos) |
| { |
| score = eMatchScoreOther; |
| } |
| |
| targetData.push_back(TargetData(targetLocalName, score, targetType)); |
| } |
| |
| opPos = nextStepPos; |
| } |
| |
| opPos = nextOpPos; |
| } |
| } |
| |
| |
| |
| bool |
| XPath::Or( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| opPos += 2; |
| |
| bool theResult; |
| |
| executeMore(context, opPos, executionContext, theResult); |
| |
| if(theResult == false) |
| { |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| executeMore(context, opPos, executionContext, theResult); |
| } |
| |
| return theResult; |
| } |
| |
| |
| |
| bool |
| XPath::And( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| opPos += 2; |
| |
| bool fResult; |
| |
| executeMore(context, opPos, executionContext, fResult); |
| |
| if (fResult == true) |
| { |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| executeMore(context, opPos, executionContext, fResult); |
| } |
| |
| return fResult; |
| } |
| |
| |
| |
| bool |
| XPath::notequals( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| opPos += 2; |
| |
| const XObjectPtr expr1(executeMore(context, opPos, executionContext)); |
| assert(expr1.get() != 0); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| return expr1->notEquals( |
| *executeMore(context, opPos, executionContext).get(), |
| executionContext); |
| } |
| |
| |
| |
| bool |
| XPath::equals( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| opPos += 2; |
| |
| const XObjectPtr expr1(executeMore(context, opPos, executionContext)); |
| assert(expr1.get() != 0); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| return expr1->equals( |
| *executeMore(context, opPos, executionContext).get(), |
| executionContext); |
| } |
| |
| |
| |
| bool |
| XPath::lte( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| opPos += 2; |
| |
| const XObjectPtr expr1(executeMore(context, opPos, executionContext)); |
| assert(expr1.get() != 0); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| return expr1->lessThanOrEquals( |
| *executeMore(context, opPos, executionContext).get(), |
| executionContext); |
| } |
| |
| |
| |
| bool |
| XPath::lt( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| opPos += 2; |
| |
| const XObjectPtr expr1(executeMore(context, opPos, executionContext)); |
| assert(expr1.get() != 0); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| return expr1->lessThan( |
| *executeMore(context, opPos, executionContext).get(), |
| executionContext); |
| } |
| |
| |
| |
| bool |
| XPath::gte( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| opPos += 2; |
| |
| const XObjectPtr expr1(executeMore(context, opPos, executionContext)); |
| assert(expr1.get() != 0); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| return expr1->greaterThanOrEquals( |
| *executeMore(context, opPos, executionContext).get(), |
| executionContext); |
| } |
| |
| |
| |
| bool |
| XPath::gt( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| opPos += 2; |
| |
| const XObjectPtr expr1(executeMore(context, opPos, executionContext)); |
| assert(expr1.get() != 0); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| return expr1->greaterThan( |
| *executeMore(context, opPos, executionContext).get(), |
| executionContext); |
| } |
| |
| |
| |
| double |
| XPath::getNumericOperand( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| if (m_expression.getOpCodeMapValue(opPos) == XPathExpression::eOP_NUMBERLIT) |
| { |
| assert(m_expression.tokenQueueSize() > |
| m_expression.getOpCodeMapValue(opPos + 3)); |
| |
| return m_expression.getNumberLiteral(m_expression.getOpCodeMapValue(opPos + 2)); |
| } |
| else |
| { |
| double theResult; |
| |
| executeMore(context, opPos, executionContext, theResult); |
| |
| return theResult; |
| } |
| } |
| |
| |
| |
| double |
| XPath::plus( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| opPos += 2; |
| |
| const double expr1 = getNumericOperand(context, opPos, executionContext); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| const double expr2 = getNumericOperand(context, opPos, executionContext); |
| |
| return DoubleSupport::add(expr1, expr2); |
| } |
| |
| |
| |
| void |
| XPath::plus( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| FormatterListener& formatterListener, |
| MemberFunctionPtr function) const |
| { |
| const double theResult = plus(context, opPos, executionContext); |
| |
| XObject::string(theResult, formatterListener, function); |
| } |
| |
| |
| |
| double |
| XPath::minus( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| opPos += 2; |
| |
| const double expr1 = getNumericOperand(context, opPos, executionContext); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| const double expr2 = getNumericOperand(context, opPos, executionContext); |
| |
| return DoubleSupport::subtract(expr1, expr2); |
| } |
| |
| |
| |
| void |
| XPath::minus( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| FormatterListener& formatterListener, |
| MemberFunctionPtr function) const |
| { |
| const double theResult = minus(context, opPos, executionContext); |
| |
| XObject::string(theResult, formatterListener, function); |
| } |
| |
| |
| |
| double |
| XPath::mult( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| opPos += 2; |
| |
| const double expr1 = getNumericOperand(context, opPos, executionContext); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| const double expr2 = getNumericOperand(context, opPos, executionContext); |
| |
| return DoubleSupport::multiply(expr1, expr2); |
| } |
| |
| |
| |
| void |
| XPath::mult( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| FormatterListener& formatterListener, |
| MemberFunctionPtr function) const |
| { |
| const double theResult = mult(context, opPos, executionContext); |
| |
| XObject::string(theResult, formatterListener, function); |
| } |
| |
| |
| |
| double |
| XPath::div( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| opPos += 2; |
| |
| const double expr1 = getNumericOperand(context, opPos, executionContext); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| const double expr2 = getNumericOperand(context, opPos, executionContext); |
| |
| return DoubleSupport::divide(expr1, expr2); |
| } |
| |
| |
| |
| void |
| XPath::div( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| FormatterListener& formatterListener, |
| MemberFunctionPtr function) const |
| { |
| const double theResult = div(context, opPos, executionContext); |
| |
| XObject::string(theResult, formatterListener, function); |
| } |
| |
| |
| |
| double |
| XPath::mod( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| opPos += 2; |
| |
| const double expr1 = getNumericOperand(context, opPos, executionContext); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| const double expr2 = getNumericOperand(context, opPos, executionContext); |
| |
| return DoubleSupport::modulus(expr1, expr2); |
| } |
| |
| |
| |
| void |
| XPath::mod( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| FormatterListener& formatterListener, |
| MemberFunctionPtr function) const |
| { |
| const double theResult = mod(context, opPos, executionContext); |
| |
| XObject::string(theResult, formatterListener, function); |
| } |
| |
| |
| |
| double |
| XPath::neg( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| return DoubleSupport::negative(getNumericOperand(context, opPos + 2, executionContext)); |
| } |
| |
| |
| |
| void |
| XPath::neg( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| FormatterListener& formatterListener, |
| MemberFunctionPtr function) const |
| { |
| const double theResult = neg(context, opPos, executionContext); |
| |
| XObject::string(theResult, formatterListener, function); |
| } |
| |
| |
| |
| const XObjectPtr |
| XPath::Union( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList resultNodeList(executionContext); |
| |
| Union(context, opPos, executionContext, *resultNodeList); |
| |
| return executionContext.getXObjectFactory().createNodeSet(resultNodeList); |
| } |
| |
| |
| |
| void |
| XPath::Union( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| bool& result) const |
| { |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList resultNodeList(executionContext); |
| |
| Union(context, opPos, executionContext, *resultNodeList); |
| |
| result = XObject::boolean(*resultNodeList); |
| } |
| |
| |
| |
| void |
| XPath::Union( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| double& result) const |
| { |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList resultNodeList(executionContext); |
| |
| Union(context, opPos, executionContext, *resultNodeList); |
| |
| result = XObject::number(executionContext, *resultNodeList); |
| } |
| |
| |
| |
| void |
| XPath::Union( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| XalanDOMString& result) const |
| { |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList resultNodeList(executionContext); |
| |
| Union(context, opPos, executionContext, *resultNodeList); |
| |
| XObject::string(*resultNodeList, executionContext, result); |
| } |
| |
| |
| |
| void |
| XPath::Union( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| FormatterListener& formatterListener, |
| MemberFunctionPtr function) const |
| { |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList resultNodeList(executionContext); |
| |
| Union(context, opPos, executionContext, *resultNodeList); |
| |
| XObject::string(*resultNodeList, executionContext, formatterListener, function); |
| } |
| |
| |
| |
| void |
| XPath::Union( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| MutableNodeRefList& result) const |
| { |
| assert(result.empty() == true); |
| |
| opPos += 2; |
| |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList theGuard(executionContext); |
| |
| MutableNodeRefList& tempNodeList = *theGuard; |
| |
| while(m_expression.getOpCodeMapValue(opPos) != XPathExpression::eENDOP) |
| { |
| const XObjectPtr nodesetResult(executeMore(context, opPos, executionContext, tempNodeList)); |
| |
| if (nodesetResult.null() == false) |
| { |
| result.addNodesInDocOrder(nodesetResult->nodeset(), executionContext); |
| } |
| else |
| { |
| result.addNodesInDocOrder(tempNodeList, executionContext); |
| |
| tempNodeList.clear(); |
| } |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| } |
| |
| result.setDocumentOrder(); |
| } |
| |
| |
| |
| const XObjectPtr |
| XPath::literal( |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| assert(m_expression.isValidOpCodePosition(opPos + 2)); |
| assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2))); |
| |
| const XToken* const theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2)); |
| assert(theLiteral != 0); |
| |
| if (m_inStylesheet == true) |
| { |
| return executionContext.getXObjectFactory().createString(*theLiteral); |
| } |
| else |
| { |
| return executionContext.getXObjectFactory().createString(theLiteral->str()); |
| } |
| } |
| |
| |
| |
| void |
| XPath::literal( |
| OpCodeMapPositionType opPos, |
| bool& theResult) const |
| { |
| assert(m_expression.isValidOpCodePosition(opPos + 2)); |
| assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2))); |
| |
| const XToken* const theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2)); |
| assert(theLiteral != 0); |
| |
| theResult = theLiteral->boolean(); |
| } |
| |
| |
| |
| void |
| XPath::literal( |
| OpCodeMapPositionType opPos, |
| double& theResult) const |
| { |
| assert(m_expression.isValidOpCodePosition(opPos + 2)); |
| assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2))); |
| |
| const XToken* const theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2)); |
| assert(theLiteral != 0); |
| |
| theResult = theLiteral->num(); |
| } |
| |
| |
| |
| void |
| XPath::literal( |
| OpCodeMapPositionType opPos, |
| XalanDOMString& theString) const |
| { |
| assert(m_expression.isValidOpCodePosition(opPos + 2)); |
| assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2))); |
| |
| const XToken* const theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2)); |
| assert(theLiteral != 0); |
| |
| theString = theLiteral->str(); |
| } |
| |
| |
| |
| void |
| XPath::literal( |
| OpCodeMapPositionType opPos, |
| FormatterListener& formatterListener, |
| MemberFunctionPtr function) const |
| { |
| assert(m_expression.isValidOpCodePosition(opPos + 2)); |
| assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2))); |
| |
| const XToken* const theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2)); |
| assert(theLiteral != 0); |
| |
| theLiteral->str(formatterListener, function); |
| } |
| |
| |
| |
| const XObjectPtr |
| XPath::variable( |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| assert(m_expression.isValidOpCodePosition(opPos + 3)); |
| assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3))); |
| |
| const XToken* const ns = |
| m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2)); |
| assert(ns != 0); |
| |
| const XToken* const varName = |
| m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3)); |
| assert(varName != 0); |
| |
| return executionContext.getVariable(XalanQNameByReference(ns->str(), varName->str()), m_locator); |
| } |
| |
| |
| |
| const XObjectPtr |
| XPath::numberlit( |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| assert(m_expression.isValidOpCodePosition(opPos + 3)); |
| assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3))); |
| |
| const XToken* const theLiteral = |
| m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3)); |
| assert(theLiteral != 0); |
| |
| if (m_inStylesheet == true) |
| { |
| return executionContext.getXObjectFactory().createNumber(*theLiteral); |
| } |
| else |
| { |
| return executionContext.getXObjectFactory().createNumber(theLiteral->num()); |
| } |
| } |
| |
| |
| |
| double |
| XPath::numberlit(OpCodeMapPositionType opPos) const |
| { |
| assert(m_expression.isValidOpCodePosition(opPos + 3)); |
| assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3))); |
| |
| const XToken* const theLiteral = |
| m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3)); |
| assert(theLiteral != 0); |
| |
| return theLiteral->num(); |
| } |
| |
| |
| |
| void |
| XPath::numberlit( |
| OpCodeMapPositionType opPos, |
| bool& theResult) const |
| { |
| assert(m_expression.isValidOpCodePosition(opPos + 3)); |
| assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3))); |
| |
| const XToken* const theLiteral = |
| m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3)); |
| assert(theLiteral != 0); |
| |
| theResult = theLiteral->boolean(); |
| } |
| |
| |
| |
| void |
| XPath::numberlit( |
| OpCodeMapPositionType opPos, |
| XalanDOMString& theString) const |
| { |
| assert(m_expression.isValidOpCodePosition(opPos + 3)); |
| assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3))); |
| |
| const XToken* const theLiteral = |
| m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3)); |
| assert(theLiteral != 0); |
| |
| theString = theLiteral->str(); |
| } |
| |
| |
| |
| void |
| XPath::numberlit( |
| OpCodeMapPositionType opPos, |
| FormatterListener& formatterListener, |
| MemberFunctionPtr function) const |
| { |
| assert(m_expression.isValidOpCodePosition(opPos + 3)); |
| assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3))); |
| |
| const XToken* const theLiteral = |
| m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3)); |
| assert(theLiteral != 0); |
| |
| theLiteral->str( formatterListener, function); |
| } |
| |
| |
| |
| const XObjectPtr |
| XPath::locationPath( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| assert(context != 0); |
| |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList mnl(executionContext); |
| |
| locationPath(context, opPos, executionContext, *mnl.get()); |
| |
| return executionContext.getXObjectFactory().createNodeSet(mnl); |
| } |
| |
| |
| |
| void |
| XPath::locationPath( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| bool& theResult) const |
| { |
| assert(context != 0); |
| |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList mnl(executionContext); |
| |
| locationPath(context, opPos, executionContext, *mnl.get()); |
| |
| theResult = XObject::boolean(*mnl.get()); |
| } |
| |
| |
| |
| void |
| XPath::locationPath( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| double& theResult) const |
| { |
| assert(context != 0); |
| |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList mnl(executionContext); |
| |
| locationPath(context, opPos, executionContext, *mnl.get()); |
| |
| theResult = XObject::number(executionContext, *mnl.get()); |
| } |
| |
| |
| |
| void |
| XPath::locationPath( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| XalanDOMString& theResult) const |
| { |
| assert(context != 0); |
| |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList mnl(executionContext); |
| |
| locationPath(context, opPos, executionContext, *mnl.get()); |
| |
| XObject::string(*mnl.get(), executionContext, theResult); |
| } |
| |
| |
| |
| void |
| XPath::locationPath( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext, |
| FormatterListener& formatterListener, |
| MemberFunctionPtr function) const |
| { |
| assert(context != 0); |
| |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList mnl(executionContext); |
| |
| locationPath(context, opPos, executionContext, *mnl.get()); |
| |
| XObject::string(*mnl, executionContext, formatterListener, function); |
| } |
| |
| |
| |
| const XObjectPtr |
| XPath::runExtFunction( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| assert(context != 0); |
| |
| const OpCodeMapPositionType endExtFunc = |
| opPos + m_expression.getOpCodeMapValue(opPos + 1) - 1; |
| |
| opPos += 2; |
| |
| const XToken* const ns = m_expression.getToken(m_expression.getOpCodeMapValue(opPos)); |
| assert(ns != 0); |
| |
| ++opPos; |
| |
| const XToken* const funcName = m_expression.getToken(m_expression.getOpCodeMapValue(opPos)); |
| assert(funcName != 0); |
| |
| ++opPos; |
| |
| typedef XPathExecutionContext::XObjectArgVectorType XObjectArgVectorType; |
| |
| XObjectArgVectorType args(executionContext.getMemoryManager()); |
| |
| while(opPos < endExtFunc) |
| { |
| const OpCodeMapPositionType nextOpPos = |
| m_expression.getNextOpCodePosition(opPos); |
| |
| args.push_back(executeMore(context, opPos, executionContext)); |
| |
| opPos = nextOpPos; |
| } |
| |
| return extfunction(context, opPos, ns->str(), funcName->str(), args, executionContext); |
| } |
| |
| |
| |
| const XObjectPtr |
| XPath::runFunction( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| const OpCodeMapPositionType endFunc = |
| opPos + m_expression.getOpCodeMapValue(opPos + 1) - 1; |
| |
| opPos += 2; |
| |
| // This is index into the function table for the |
| // function. |
| const OpCodeMapValueType funcID = m_expression.getOpCodeMapValue(opPos); |
| |
| opPos++; |
| |
| // Number of args is next. |
| const OpCodeMapValueType argCount = m_expression.getOpCodeMapValue(opPos); |
| |
| opPos++; |
| |
| if (argCount == 0) |
| { |
| assert(opPos == endFunc); |
| |
| return s_functions[funcID].execute(executionContext, context, m_locator); |
| } |
| else if (argCount == 1) |
| { |
| return s_functions[funcID].execute( |
| executionContext, |
| context, |
| executeMore(context, opPos, executionContext), |
| m_locator); |
| } |
| else if (argCount == 2) |
| { |
| const XObjectPtr theArg1(executeMore(context, opPos, executionContext)); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| assert(m_expression.getNextOpCodePosition(opPos) == endFunc); |
| |
| return s_functions[funcID].execute( |
| executionContext, |
| context, |
| theArg1, |
| executeMore(context, opPos, executionContext), |
| m_locator); |
| } |
| else if (argCount == 3) |
| { |
| const XObjectPtr theArg1(executeMore(context, opPos, executionContext)); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| const XObjectPtr theArg2(executeMore(context, opPos, executionContext)); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| |
| assert(m_expression.getNextOpCodePosition(opPos) == endFunc); |
| |
| return s_functions[funcID].execute( |
| executionContext, |
| context, |
| theArg1, |
| theArg2, |
| executeMore(context, opPos, executionContext), |
| m_locator); |
| } |
| else |
| { |
| typedef XPathExecutionContext::XObjectArgVectorType XObjectArgVectorType; |
| |
| XObjectArgVectorType args(executionContext.getMemoryManager()); |
| |
| args.reserve(argCount); |
| |
| while(opPos < endFunc) |
| { |
| args.push_back(executeMore(context, opPos, executionContext)); |
| |
| opPos = m_expression.getNextOpCodePosition(opPos); |
| } |
| |
| return function(context, funcID, args, executionContext); |
| } |
| } |
| |
| |
| |
| double |
| XPath::functionCount( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| assert(context != 0); |
| |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList result(executionContext); |
| |
| const XObjectPtr nodesetResult(executeMore(context, opPos + 2, executionContext, *result)); |
| |
| const XPathExecutionContext::size_type theResult = |
| nodesetResult.null() == false ? |
| nodesetResult->nodeset().getLength() : |
| result->getLength(); |
| assert(static_cast<double>(theResult) == theResult); |
| |
| return static_cast<double>(theResult); |
| } |
| |
| |
| |
| const XalanDOMString& |
| XPath::functionName( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| assert(context != 0); |
| |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList result(executionContext); |
| |
| const XObjectPtr nodesetResult(executeMore(context, opPos + 2, executionContext, *result)); |
| |
| const NodeRefListBase* const theNodeList = nodesetResult.null() == false ? |
| &nodesetResult->nodeset() : &*result; |
| assert(theNodeList != 0); |
| |
| if (theNodeList->getLength() == 0) |
| { |
| return s_emptyString; |
| } |
| else |
| { |
| assert(theNodeList->item(0) != 0); |
| |
| return functionName(theNodeList->item(0)); |
| } |
| } |
| |
| |
| |
| const XalanDOMString& |
| XPath::functionLocalName(XalanNode* context) const |
| { |
| assert(context != 0); |
| |
| const XalanDOMString* theResult = &s_emptyString; |
| |
| const XalanNode::NodeType theType = context->getNodeType(); |
| |
| if(theType == XalanNode::ELEMENT_NODE || |
| theType == XalanNode::PROCESSING_INSTRUCTION_NODE) |
| { |
| theResult = &DOMServices::getLocalNameOfNode(*context); |
| } |
| else if (theType == XalanNode::ATTRIBUTE_NODE) |
| { |
| const XalanDOMString& theLocalName = DOMServices::getLocalNameOfNode(*context); |
| |
| if (theLocalName != DOMServices::s_XMLNamespace) |
| { |
| theResult = &theLocalName; |
| } |
| } |
| |
| return *theResult; |
| } |
| |
| |
| |
| const XalanDOMString& |
| XPath::functionLocalName( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| assert(context != 0); |
| |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList result(executionContext); |
| |
| const XObjectPtr nodesetResult(executeMore(context, opPos + 2, executionContext, *result)); |
| |
| const NodeRefListBase* const theNodeList = nodesetResult.null() == false ? |
| &nodesetResult->nodeset() : &*result; |
| assert(theNodeList != 0); |
| |
| if (theNodeList->getLength() == 0) |
| { |
| return s_emptyString; |
| } |
| else |
| { |
| assert(theNodeList->item(0) != 0); |
| |
| return functionLocalName(theNodeList->item(0)); |
| } |
| } |
| |
| |
| |
| double |
| XPath::functionStringLength( |
| XalanNode* context, |
| XPathExecutionContext& executionContext) const |
| { |
| assert(context != 0); |
| |
| FormatterStringLengthCounter theCounter; |
| |
| DOMServices::getNodeData(*context, executionContext, theCounter, &FormatterListener::characters); |
| |
| const FormatterListener::size_type theResult = theCounter.getCount(); |
| assert(static_cast<double>(theResult) == theResult); |
| |
| return static_cast<double>(theResult); |
| } |
| |
| |
| |
| double |
| XPath::functionStringLength( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| assert(context != 0); |
| |
| FormatterStringLengthCounter theCounter; |
| |
| executeMore(context, opPos + 2, executionContext, theCounter, &FormatterListener::characters); |
| |
| const FormatterListener::size_type theResult = theCounter.getCount(); |
| assert(static_cast<double>(theResult) == theResult); |
| |
| return static_cast<double>(theResult); |
| } |
| |
| |
| |
| double |
| XPath::functionSum( |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| XPathExecutionContext& executionContext) const |
| { |
| assert(context != 0); |
| |
| double sum = 0.0; |
| |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList result(executionContext); |
| |
| const XObjectPtr nodesetResult(executeMore(context, opPos + 2, executionContext, *result)); |
| |
| const NodeRefListBase* const theNodeList = nodesetResult.null() == false ? |
| &nodesetResult->nodeset() : &*result; |
| assert(theNodeList != 0); |
| |
| const NodeRefListBase::size_type theLength = theNodeList->getLength(); |
| |
| if (theLength != 0) |
| { |
| assert(theNodeList->item(0) != 0); |
| |
| const GetCachedString theData(executionContext); |
| |
| XalanDOMString& theString = theData.get(); |
| |
| for (NodeRefListBase::size_type i = 0; i < theLength; i++) |
| { |
| DOMServices::getNodeData(*theNodeList->item(i), executionContext, theString); |
| |
| sum = DoubleSupport::add(sum, DoubleSupport::toDouble(theString, executionContext.getMemoryManager())); |
| |
| theString.clear(); |
| } |
| } |
| |
| return sum; |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::locationPathPattern( |
| XPathExecutionContext& executionContext, |
| XalanNode& context, |
| OpCodeMapPositionType opPos) const |
| { |
| eMatchScore score = eMatchScoreNone; |
| |
| stepPattern(executionContext, &context, opPos + 2, score); |
| |
| return score; |
| } |
| |
| |
| |
| void |
| XPath::step( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| MutableNodeRefList& queryResults) const |
| { |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType stepType = |
| currentExpression.getOpCodeMapValue(opPos); |
| |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList subQueryResults(executionContext); |
| |
| bool continueStepRecursion = true; |
| |
| switch(stepType) |
| { |
| case XPathExpression::eOP_VARIABLE: |
| case XPathExpression::eOP_EXTFUNCTION: |
| case XPathExpression::eOP_FUNCTION: |
| case XPathExpression::eOP_GROUP: |
| opPos = findNodeSet(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| case XPathExpression::eFROM_ROOT: |
| opPos = findRoot(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| case XPathExpression::eFROM_PARENT: |
| opPos = findParent(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| case XPathExpression::eFROM_SELF: |
| opPos = findSelf(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| case XPathExpression::eFROM_ANCESTORS: |
| opPos = findAncestors(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| case XPathExpression::eFROM_ANCESTORS_OR_SELF: |
| opPos = findAncestorsOrSelf(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| case XPathExpression::eMATCH_ATTRIBUTE: |
| continueStepRecursion = false; |
| // fall-through on purpose. |
| |
| case XPathExpression::eFROM_ATTRIBUTES: |
| opPos = findAttributes(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| case XPathExpression::eMATCH_ANY_ANCESTOR: |
| case XPathExpression::eMATCH_IMMEDIATE_ANCESTOR: |
| case XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE: |
| continueStepRecursion = false; |
| // fall-through on purpose. |
| |
| case XPathExpression::eFROM_CHILDREN: |
| opPos = findChildren(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| case XPathExpression::eFROM_DESCENDANTS: |
| case XPathExpression::eFROM_DESCENDANTS_OR_SELF: |
| opPos = findDescendants(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| case XPathExpression::eFROM_FOLLOWING: |
| opPos = findFollowing(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| case XPathExpression::eFROM_FOLLOWING_SIBLINGS: |
| opPos = findFollowingSiblings(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| case XPathExpression::eFROM_PRECEDING: |
| opPos = findPreceeding(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| case XPathExpression::eFROM_PRECEDING_SIBLINGS: |
| opPos = findPreceedingSiblings(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| case XPathExpression::eFROM_NAMESPACE: |
| opPos = findNamespace(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| |
| default: |
| opPos = findNodesOnUnknownAxis(executionContext, context, opPos, stepType, *subQueryResults); |
| break; |
| } |
| |
| OpCodeMapValueType nextStepType = currentExpression.getOpCodeMapValue(opPos); |
| |
| // Push and pop the context node list... |
| XPathExecutionContext::ContextNodeListPushAndPop thePushAndPop( |
| executionContext, |
| *subQueryResults); |
| |
| if(XPathExpression::eOP_PREDICATE == nextStepType || |
| XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType) |
| { |
| opPos = |
| predicates( |
| executionContext, |
| opPos, |
| *subQueryResults); |
| |
| nextStepType = currentExpression.getOpCodeMapValue(opPos); |
| } |
| |
| if(XPathExpression::eENDOP != nextStepType && continueStepRecursion == true) |
| { |
| const NodeRefListBase::size_type nContexts = subQueryResults->getLength(); |
| |
| if (nContexts > 0) |
| { |
| for(NodeRefListBase::size_type i = 0; i < nContexts; i++) |
| { |
| XalanNode* const node = subQueryResults->item(i); |
| assert(node != 0); |
| |
| BorrowReturnMutableNodeRefList mnl(executionContext); |
| |
| step(executionContext, node, opPos, *mnl); |
| |
| if (mnl->empty() == false) |
| { |
| if(queryResults.empty() == false) |
| { |
| queryResults.addNodesInDocOrder(*mnl, executionContext); |
| |
| queryResults.setDocumentOrder(); |
| } |
| else |
| { |
| assert(mnl->getDocumentOrder() == true); |
| |
| queryResults.swap(*mnl); |
| } |
| } |
| } |
| |
| if (queryResults.empty() == true) |
| { |
| queryResults.setDocumentOrder(); |
| } |
| } |
| } |
| else |
| { |
| if (subQueryResults->empty() == true) |
| { |
| queryResults.clear(); |
| |
| queryResults.setDocumentOrder(); |
| } |
| else if (subQueryResults->getReverseDocumentOrder() == true) |
| { |
| queryResults.swap(*subQueryResults); |
| |
| queryResults.reverse(); |
| } |
| else |
| { |
| assert(subQueryResults->getDocumentOrder() == true); |
| |
| queryResults.swap(*subQueryResults); |
| } |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::doStepPredicate( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapPositionType startOpPos, |
| eMatchScore score) const |
| { |
| const XPathExpression& currentExpression = getExpression(); |
| |
| OpCodeMapValueType nextStepType = currentExpression.getOpCodeMapValue(opPos); |
| |
| if (XPathExpression::eOP_PREDICATE == nextStepType || |
| XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType) |
| { |
| do |
| { |
| // This is a quick hack to look ahead and see if we have |
| // number literal as the predicate, i.e. match="foo[1]". |
| if (XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType) |
| { |
| if (m_expression.getOpCodeMapValue(opPos + 2) == XPathExpression::eOP_NUMBERLIT) |
| { |
| score = handleFoundIndexPositional( |
| executionContext, |
| context, |
| startOpPos); |
| } |
| else |
| { |
| score = handleFoundIndex( |
| executionContext, |
| context, |
| startOpPos); |
| } |
| } |
| else |
| { |
| const XObjectPtr pred(predicate(context, opPos, executionContext)); |
| assert(pred.get() != 0); |
| |
| if(XObject::eTypeNumber == pred->getType()) |
| { |
| score = handleFoundIndex(executionContext, context, startOpPos); |
| } |
| else if(pred->boolean(executionContext) == false) |
| { |
| score = eMatchScoreNone; |
| |
| break; |
| } |
| } |
| |
| opPos = currentExpression.getNextOpCodePosition(opPos); |
| nextStepType = currentExpression.getOpCodeMapValue(opPos); |
| } |
| while(XPathExpression::eOP_PREDICATE == nextStepType || |
| XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType); |
| } |
| |
| return score; |
| } |
| |
| |
| |
| XalanNode* |
| XPath::stepPattern( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| eMatchScore& scoreHolder) const |
| { |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapPositionType endStep = currentExpression.getNextOpCodePosition(opPos); |
| OpCodeMapValueType nextStepType = currentExpression.getOpCodeMapValue(endStep); |
| |
| bool fDoPredicates = true; |
| |
| if(XPathExpression::eENDOP != nextStepType) |
| { |
| // Continue step via recursion... |
| context = stepPattern( |
| executionContext, |
| context, |
| endStep, |
| scoreHolder); |
| |
| if(0 == context) |
| { |
| scoreHolder = eMatchScoreNone; |
| |
| } |
| |
| if (scoreHolder == eMatchScoreNone) |
| { |
| // !!!!!!!!!!!!! Big ugly return here !!!!!!!!!!!!!!!!!!! |
| return 0; |
| } |
| |
| scoreHolder = eMatchScoreOther; |
| |
| if (nextStepType != XPathExpression::eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL) |
| { |
| context = DOMServices::getParentOfNode(*context); |
| } |
| |
| if(0 == context) |
| { |
| // !!!!!!!!!!!!! Big ugly return here !!!!!!!!!!!!!!!!!!! |
| return 0; |
| } |
| } |
| |
| assert(context != 0); |
| |
| OpCodeMapValueType argLen = 0; |
| |
| eMatchScore score = eMatchScoreNone; |
| |
| const OpCodeMapPositionType startOpPos = opPos; |
| const OpCodeMapValueType stepType = |
| currentExpression.getOpCodeMapValue(opPos); |
| |
| switch(stepType) |
| { |
| case XPathExpression::eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL: |
| score = scoreHolder; |
| break; |
| |
| case XPathExpression::eOP_FUNCTION: |
| { |
| argLen = currentExpression.getOpCodeLengthFromOpMap(opPos, |
| executionContext.getMemoryManager()); |
| |
| const XObjectPtr obj(executeMore(context, opPos, executionContext)); |
| assert(obj.get() != 0); |
| |
| const NodeRefListBase& nl = obj->nodeset(); |
| |
| const NodeRefListBase::size_type len = nl.getLength(); |
| |
| if (nextStepType == XPathExpression::eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL) |
| { |
| bool fFound = false; |
| |
| while(context != 0 && fFound == false) |
| { |
| for(NodeRefListBase::size_type i = 0; i < len; i++) |
| { |
| XalanNode* const n = nl.item(i); |
| |
| if(n == context) |
| { |
| score = eMatchScoreOther; |
| |
| context = n; |
| |
| fFound = true; |
| |
| break; |
| } |
| } |
| |
| context = DOMServices::getParentOfNode(*context); |
| } |
| } |
| else |
| { |
| for(NodeRefListBase::size_type i = 0; i < len; i++) |
| { |
| XalanNode* const n = nl.item(i); |
| |
| if(n == context) |
| { |
| score = eMatchScoreOther; |
| |
| context = n; |
| |
| break; |
| } |
| } |
| } |
| } |
| break; |
| |
| case XPathExpression::eFROM_ROOT: |
| { |
| argLen = currentExpression.getOpCodeArgumentLength(opPos); |
| |
| opPos += 3; |
| |
| const XalanNode::NodeType nodeType = context->getNodeType(); |
| |
| if (nodeType == XalanNode::DOCUMENT_NODE || |
| nodeType == XalanNode::DOCUMENT_FRAGMENT_NODE) |
| { |
| score = eMatchScoreOther; |
| } |
| else |
| { |
| const OpCodeMapPositionType prevPos = currentExpression.getNextOpCodePosition(startOpPos); |
| const OpCodeMapValueType prevStepType = currentExpression.getOpCodeMapValue(prevPos); |
| |
| if (eMatchScoreNone == score && |
| (prevStepType == XPathExpression::eMATCH_ANY_ANCESTOR || |
| prevStepType == XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE)) |
| { |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| while(0 != context) |
| { |
| score = |
| theTester(*context, context->getNodeType()); |
| |
| if(eMatchScoreNone != score) |
| break; |
| |
| context = DOMServices::getParentOfNode(*context); |
| } |
| } |
| } |
| } |
| break; |
| |
| case XPathExpression::eMATCH_ATTRIBUTE: |
| { |
| argLen = currentExpression.getOpCodeArgumentLength(opPos); |
| |
| opPos += 3; |
| |
| score = NodeTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| XPathExpression::eFROM_ATTRIBUTES)(*context, context->getNodeType()); |
| } |
| break; |
| |
| case XPathExpression::eMATCH_ANY_ANCESTOR: |
| case XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE: |
| { |
| assert(fDoPredicates == true); |
| fDoPredicates = false; |
| |
| argLen = currentExpression.getOpCodeArgumentLength(opPos); |
| |
| XalanNode::NodeType nodeType = context->getNodeType(); |
| |
| if(nodeType != XalanNode::ATTRIBUTE_NODE) |
| { |
| opPos += 3; |
| |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| for(;;) |
| { |
| score = theTester(*context, nodeType); |
| |
| if (eMatchScoreNone != score) |
| { |
| score = |
| doStepPredicate( |
| executionContext, |
| context, |
| opPos + argLen, |
| startOpPos, |
| score); |
| if (eMatchScoreNone != score) |
| { |
| break; |
| } |
| } |
| |
| context = DOMServices::getParentOfNode(*context); |
| |
| if (context == 0) |
| break; |
| |
| nodeType = context->getNodeType(); |
| } |
| } |
| } |
| break; |
| |
| case XPathExpression::eMATCH_IMMEDIATE_ANCESTOR: |
| { |
| argLen = currentExpression.getOpCodeArgumentLength(opPos); |
| |
| const XalanNode::NodeType nodeType = context->getNodeType(); |
| |
| if(nodeType != XalanNode::ATTRIBUTE_NODE) |
| { |
| opPos += 3; |
| |
| score = NodeTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| XPathExpression::eMATCH_IMMEDIATE_ANCESTOR)(*context, nodeType); |
| } |
| } |
| break; |
| |
| default: |
| { |
| const GetCachedString theGuard1(executionContext); |
| const GetCachedString theGuard2(executionContext); |
| |
| executionContext.problem( |
| XPathExecutionContext::eXPath, |
| XPathExecutionContext::eError, |
| XalanMessageLoader::getMessage( |
| theGuard1.get(), |
| XalanMessages::UnknownMatchOpCode_1Param, |
| NumberToDOMString( |
| stepType, |
| theGuard2.get())), |
| getLocator(), |
| context); |
| |
| break; |
| } |
| } |
| |
| if (fDoPredicates == true && score != eMatchScoreNone) |
| { |
| score = |
| doStepPredicate( |
| executionContext, |
| context, |
| opPos + argLen, |
| startOpPos, |
| score); |
| } |
| |
| if (scoreHolder == eMatchScoreNone || |
| score == eMatchScoreNone) |
| { |
| scoreHolder = score; |
| } |
| |
| return score == eMatchScoreNone ? 0 : context; |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::handleFoundIndex( |
| XPathExecutionContext& executionContext, |
| XalanNode* localContext, |
| OpCodeMapPositionType startOpPos) const |
| { |
| // We have an index somewhere in our pattern. So, we have |
| // to do a full search for our step, using the parent as |
| // localContext, then see if the current localContext is found in the |
| // node set. Seems crazy, but, so far, it seems like the |
| // easiest way. |
| XalanNode* const parentContext = |
| DOMServices::getParentOfNode(*localContext); |
| |
| if (parentContext == 0) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList mnl(executionContext); |
| |
| step(executionContext, parentContext, startOpPos, *mnl); |
| |
| if (mnl->indexOf(localContext) == MutableNodeRefList::npos) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreOther; |
| } |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::handleFoundIndexPositional( |
| XPathExecutionContext& executionContext, |
| XalanNode* localContext, |
| OpCodeMapPositionType startOpPos) const |
| { |
| XalanNode* const parentContext = |
| DOMServices::getParentOfNode(*localContext); |
| |
| if (parentContext == 0) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList; |
| |
| BorrowReturnMutableNodeRefList mnl(executionContext); |
| |
| step(executionContext, parentContext, startOpPos, *mnl); |
| |
| if (mnl->empty() == true) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| assert(mnl->getLength() == 1 && mnl->item(0) == localContext); |
| |
| return eMatchScoreOther; |
| } |
| } |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findNodeSet( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType /* stepType */, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(subQueryResults.empty() == true); |
| |
| const XObjectPtr nodesetResult(executeMore(context, opPos, executionContext, subQueryResults)); |
| |
| if (nodesetResult.null() == true) |
| { |
| assert(subQueryResults.getDocumentOrder()); |
| } |
| else |
| { |
| subQueryResults.addNodesInDocOrder(nodesetResult->nodeset(), executionContext); |
| |
| subQueryResults.setDocumentOrder(); |
| } |
| |
| return opPos + getExpression().getOpCodeLengthFromOpMap(opPos, executionContext.getMemoryManager()); |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findRoot( |
| XPathExecutionContext& /* executionContext */, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType /* stepType */, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(context != 0); |
| assert(subQueryResults.empty() == true); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| XalanNode::NodeType nodeType = |
| context->getNodeType(); |
| |
| XalanNode* docContext = |
| nodeType == XalanNode::DOCUMENT_NODE ? |
| context : |
| context->getOwnerDocument(); |
| |
| // This is a special case for RTFs, as the "owner document" is |
| // just a factory for the RTF. Instead, we have to search for |
| // the containing XalanDocumentFragment node. |
| if (static_cast<const XalanDocument*>(docContext)->getDocumentElement() == 0) |
| { |
| docContext = context; |
| |
| for(;;) |
| { |
| if (nodeType == XalanNode::DOCUMENT_FRAGMENT_NODE) |
| { |
| break; |
| } |
| else |
| { |
| docContext = |
| DOMServices::getParentOfNode(*docContext); |
| assert(docContext != 0); |
| |
| nodeType = docContext->getNodeType(); |
| |
| } |
| } |
| } |
| |
| assert(docContext != 0); |
| |
| subQueryResults.addNode(docContext); |
| |
| subQueryResults.setDocumentOrder(); |
| |
| return opPos + argLen + 3; |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findParent( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType stepType, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(subQueryResults.empty() == true); |
| assert(context != 0); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| XalanNode* const theParent = DOMServices::getParentOfNode(*context); |
| |
| opPos += 3; |
| |
| if(0 != theParent) |
| { |
| if(argLen > 0) |
| { |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| const eMatchScore score = theTester(*theParent, theParent->getNodeType()); |
| |
| if(eMatchScoreNone != score) |
| { |
| subQueryResults.addNode(theParent); |
| } |
| } |
| else |
| { |
| subQueryResults.addNode(theParent); |
| } |
| } |
| |
| subQueryResults.setDocumentOrder(); |
| |
| return opPos + argLen; |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findSelf( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType stepType, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(subQueryResults.empty() == true); |
| assert(context != 0); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| opPos += 3; |
| |
| if(argLen == 0) |
| { |
| subQueryResults.addNode(context); |
| } |
| else |
| { |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| const eMatchScore score = |
| theTester(*context, context->getNodeType()); |
| |
| if(eMatchScoreNone != score) |
| { |
| subQueryResults.addNode(context); |
| } |
| } |
| |
| subQueryResults.setDocumentOrder(); |
| |
| return opPos + argLen; |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findAncestors( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType stepType, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(subQueryResults.empty() == true); |
| assert(context != 0); |
| |
| context = DOMServices::getParentOfNode(*context); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| opPos += 3; |
| |
| if (context != 0) |
| { |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| do |
| { |
| const eMatchScore score = |
| theTester(*context, context->getNodeType()); |
| |
| if(eMatchScoreNone != score) |
| { |
| subQueryResults.addNode(context); |
| } |
| |
| context = DOMServices::getParentOfNode(*context); |
| } while(0 != context); |
| } |
| |
| subQueryResults.setReverseDocumentOrder(); |
| |
| return opPos + argLen; |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findAncestorsOrSelf( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType stepType, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(subQueryResults.empty() == true); |
| assert(context != 0); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| opPos += 3; |
| |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| do |
| { |
| const eMatchScore score = |
| theTester(*context, context->getNodeType()); |
| |
| if(eMatchScoreNone != score) |
| { |
| subQueryResults.addNode(context); |
| } |
| |
| context = DOMServices::getParentOfNode(*context); |
| } while(0 != context); |
| |
| subQueryResults.setReverseDocumentOrder(); |
| |
| return opPos + argLen; |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findAttributes( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType stepType, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(subQueryResults.empty() == true); |
| assert(context != 0); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| opPos += 3; |
| |
| if(context->getNodeType() == XalanNode::ELEMENT_NODE) |
| { |
| const XalanNamedNodeMap* const attributeList = context->getAttributes(); |
| |
| if(attributeList != 0) |
| { |
| const XalanSize_t nAttrs = attributeList->getLength(); |
| |
| if (nAttrs != 0) |
| { |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| for (XalanSize_t j = 0; j < nAttrs; j++) |
| { |
| XalanNode* const theNode = attributeList->item(j); |
| assert(theNode != 0 && theNode->getNodeType() == XalanNode::ATTRIBUTE_NODE); |
| |
| const eMatchScore score = |
| theTester(*theNode, XalanNode::ATTRIBUTE_NODE); |
| |
| if(eMatchScoreNone != score) |
| { |
| subQueryResults.addNode(theNode); |
| } |
| } |
| } |
| } |
| } |
| |
| subQueryResults.setDocumentOrder(); |
| |
| return opPos + argLen; |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findChildren( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType stepType, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(subQueryResults.empty() == true); |
| assert(context != 0); |
| |
| XalanNode* child = context->getFirstChild(); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| opPos += 3; |
| |
| if (child != 0) |
| { |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| do |
| { |
| const eMatchScore score = |
| theTester(*child, child->getNodeType()); |
| |
| if(eMatchScoreNone != score) |
| { |
| subQueryResults.addNode(child); |
| } |
| |
| child = child->getNextSibling(); |
| } while(0 != child); |
| } |
| |
| subQueryResults.setDocumentOrder(); |
| |
| return opPos + argLen; |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findDescendants( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType stepType, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(subQueryResults.empty() == true); |
| assert(context != 0); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| // Perform a pre-order traversal of descendents... |
| XalanNode* pos = context; |
| |
| opPos += 3; |
| |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| do |
| { |
| if(stepType == XPathExpression::eFROM_DESCENDANTS_OR_SELF || |
| context != pos) |
| { |
| const eMatchScore score = |
| theTester(*pos, pos->getNodeType()); |
| |
| if(score != eMatchScoreNone) |
| { |
| subQueryResults.addNode(pos); |
| } |
| } |
| |
| XalanNode* nextNode = pos->getFirstChild(); |
| |
| while(0 == nextNode) |
| { |
| if(context == pos) |
| break; |
| |
| nextNode = pos->getNextSibling(); |
| |
| if(0 == nextNode) |
| { |
| pos = DOMServices::getParentOfNode(*pos); |
| |
| if(context == pos || pos == 0) |
| { |
| nextNode = 0; |
| break; |
| } |
| } |
| } |
| |
| pos = nextNode; |
| } while(0 != pos); |
| |
| subQueryResults.setDocumentOrder(); |
| |
| return opPos + argLen; |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findFollowing( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType stepType, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(subQueryResults.empty() == true); |
| assert(context != 0); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| opPos += 3; |
| |
| // What fun... |
| XalanDocument* const doc = context->getOwnerDocument(); |
| |
| XalanNode* pos = context; |
| |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| while(0 != pos) |
| { |
| XalanNode* nextNode = 0; |
| |
| if(pos != context) |
| { |
| const eMatchScore score = |
| theTester(*pos, pos->getNodeType()); |
| |
| if(eMatchScoreNone != score) |
| { |
| subQueryResults.addNodeInDocOrder(pos, executionContext); |
| } |
| |
| nextNode = pos->getFirstChild(); |
| } |
| else |
| { |
| nextNode = 0; |
| } |
| |
| while(0 == nextNode) |
| { |
| // This requires some explanation. pos could be an attribute |
| // node, so getNextSibling() will always return 0. In that |
| // case, I want to continue the search with the first child of |
| // the owner element, as if attribute nodes are children which |
| // are always _before_ the first child element. I don't have to |
| // consider following attributes, since they _never_ match the |
| // following axis. |
| if (pos->getNodeType() == XalanNode::ATTRIBUTE_NODE) |
| { |
| assert(DOMServices::getParentOfNode(*pos) != 0); |
| |
| nextNode = DOMServices::getParentOfNode(*pos)->getFirstChild(); |
| } |
| else |
| { |
| nextNode = pos->getNextSibling(); |
| } |
| |
| if(0 == nextNode) |
| { |
| pos = DOMServices::getParentOfNode(*pos); |
| |
| if(doc == pos || 0 == pos) |
| { |
| nextNode = 0; |
| |
| break; |
| } |
| } |
| } |
| |
| pos = nextNode; |
| } |
| |
| subQueryResults.setDocumentOrder(); |
| |
| return opPos + argLen; |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findFollowingSiblings( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType stepType, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(subQueryResults.empty() == true); |
| assert(context != 0); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| XalanNode* pos = context->getNextSibling(); |
| |
| opPos += 3; |
| |
| if (pos != 0) |
| { |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| do |
| { |
| const eMatchScore score = |
| theTester(*pos, pos->getNodeType()); |
| |
| if(eMatchScoreNone != score) |
| { |
| subQueryResults.addNode(pos); |
| } |
| |
| pos = pos->getNextSibling(); |
| } while(0 != pos); |
| } |
| |
| subQueryResults.setDocumentOrder(); |
| |
| return opPos + argLen; |
| } |
| |
| |
| |
| /* |
| * This is bit of a hack to figure out where we should start for |
| * the preceeding axis. It's mostly to support RTFs which have |
| * been coerced to nodesets through the nodeset() extension function. |
| */ |
| static XalanNode* |
| findTopNode( |
| XalanNode* context, |
| XalanNode::NodeType theType) |
| { |
| assert(context != 0); |
| |
| if (theType == XalanNode::DOCUMENT_NODE) |
| { |
| return context; |
| } |
| else |
| { |
| XalanDocument* const theDocument = context->getOwnerDocument(); |
| assert(theDocument != 0); |
| |
| if (theDocument->getDocumentElement() != 0) |
| { |
| return theDocument; |
| } |
| else |
| { |
| XalanNode* theNode = 0; |
| |
| while(context != 0 && |
| context->getNodeType() != XalanNode::DOCUMENT_NODE) |
| { |
| theNode = context; |
| |
| context = DOMServices::getParentOfNode(*context); |
| } |
| |
| assert(theNode != 0); |
| |
| return theNode; |
| } |
| } |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findPreceeding( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType stepType, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(subQueryResults.empty() == true); |
| assert(context != 0); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| opPos += 3; |
| |
| // Ugh. Reverse document order, no parents, I guess. |
| const XalanNode::NodeType theType = context->getNodeType(); |
| |
| XalanNode* const topNode = findTopNode(context, theType); |
| |
| XalanNode* pos = topNode; |
| |
| // If the context node is an attribute, we need to perform some |
| // magic to stop the search at the appropriate point, which is when |
| // we arrive back at the parent. |
| const bool contextIsAttribute = |
| theType == XalanNode::ATTRIBUTE_NODE ? true : false; |
| |
| const XalanNode* const theAttributeContextParent = |
| contextIsAttribute == true ? DOMServices::getParentOfNode(*context) : 0; |
| |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| while(0 != pos) |
| { |
| if(context == pos) |
| { |
| break; |
| } |
| |
| const eMatchScore score = |
| theTester(*pos, pos->getNodeType()); |
| |
| if(eMatchScoreNone != score) |
| { |
| // Ugh. If I could think a little better tonight, I'm |
| // sure there's a better way to check for the parent. |
| bool isParent = false; |
| |
| XalanNode* parent = DOMServices::getParentOfNode(*context); |
| |
| while(0 != parent) |
| { |
| if(parent == pos) |
| { |
| isParent = true; |
| break; |
| } |
| |
| parent = DOMServices::getParentOfNode(*parent); |
| } |
| |
| if(isParent == false) |
| { |
| subQueryResults.addNode(pos); |
| } |
| } |
| |
| XalanNode* nextNode = 0; |
| |
| // Check to see if we're back at the attribute context node's |
| // parent, in which case, we should stop. |
| if (contextIsAttribute == true && |
| pos == theAttributeContextParent) |
| { |
| nextNode = context; |
| } |
| else |
| { |
| nextNode = pos->getFirstChild(); |
| } |
| |
| while(0 == nextNode) |
| { |
| nextNode = pos->getNextSibling(); |
| |
| if(0 == nextNode) |
| { |
| pos = DOMServices::getParentOfNode(*pos); |
| |
| if(topNode == pos) |
| { |
| nextNode = 0; |
| break; |
| } |
| } |
| } |
| |
| pos = nextNode; |
| } |
| |
| // Now, reverse the order of the nodes, since |
| // preceeding is a reverse axis, and we searched |
| // the document from the root to this node. |
| subQueryResults.reverse(); |
| |
| subQueryResults.setReverseDocumentOrder(); |
| |
| return opPos + argLen; |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findPreceedingSiblings( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType stepType, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(subQueryResults.empty() == true); |
| assert(context != 0); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| opPos += 3; |
| |
| #if 1 |
| XalanNode* pos = context->getPreviousSibling(); |
| |
| if (pos != 0) |
| { |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| do |
| { |
| const eMatchScore score = |
| theTester(*pos, pos->getNodeType()); |
| |
| if(eMatchScoreNone != score) |
| { |
| subQueryResults.addNode(pos); |
| } |
| |
| pos = pos->getPreviousSibling(); |
| } while(0 != pos); |
| } |
| #else |
| // This is some experimental code which avoids using getPreviousSibling(), with the idea that we |
| // could reduce our in-memory representation size by not keeping the previous sibling node. |
| XalanNode* pos = context->getParentNode(); |
| |
| if (pos != 0) |
| { |
| pos = pos->getFirstChild(); |
| |
| if (pos != context) |
| { |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| do |
| { |
| const eMatchScore score = |
| theTester(*pos, pos->getNodeType()); |
| |
| if(eMatchScoreNone != score) |
| { |
| subQueryResults.addNode(pos); |
| } |
| |
| pos = pos->getNextSibling(); |
| } while(pos != context); |
| } |
| |
| // Now, reverse the order of the nodes, since |
| // preceeding-sibling is a reverse axis, and we searched |
| // the document from the root to this node. |
| subQueryResults.reverse(); |
| } |
| #endif |
| |
| subQueryResults.setReverseDocumentOrder(); |
| |
| return opPos + argLen; |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findNamespace( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType stepType, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(subQueryResults.empty() == true); |
| assert(context != 0); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| opPos += 3; |
| |
| if(context->getNodeType() == XalanNode::ELEMENT_NODE) |
| { |
| // Look up the element chain until we hit the document, so that we |
| // get all of the attribute/namespace nodes. |
| const XalanNode* const theOwnerDocument = context->getOwnerDocument(); |
| assert(theOwnerDocument != 0); |
| |
| const XalanNode* theCurrentNode = context; |
| |
| const NodeTester theTester( |
| *this, |
| executionContext, |
| opPos, |
| argLen, |
| stepType); |
| |
| NodeRefListBase::size_type nNSFound = 0; |
| bool defaultNSFound = false; |
| |
| do |
| { |
| const XalanNamedNodeMap* const attributeList = |
| theCurrentNode->getAttributes(); |
| |
| if(attributeList != 0) |
| { |
| XalanSize_t nAttrs = attributeList->getLength(); |
| |
| while (nAttrs > 0) |
| { |
| --nAttrs; |
| |
| XalanNode* const attr = attributeList->item(nAttrs); |
| assert(attr != 0 && attr->getNodeType() == XalanNode::ATTRIBUTE_NODE); |
| |
| const XalanDOMString& theNodeName = attr->getNodeName(); |
| |
| // This is an optimization to keep non-namespace attributes out of |
| // the call to the NodeTester. |
| if (startsWith(theNodeName, DOMServices::s_XMLNamespaceWithSeparator) == true || |
| theNodeName == DOMServices::s_XMLNamespace) |
| { |
| const eMatchScore score = |
| theTester(*attr, XalanNode::ATTRIBUTE_NODE); |
| |
| if(score != eMatchScoreNone) |
| { |
| const XalanDOMString& theNodeValue = attr->getNodeValue(); |
| |
| bool foundNSMatch = false; |
| |
| // Need to check default NS slightly differently |
| if (theNodeName == DOMServices::s_XMLNamespace) |
| { |
| // If namespace is empty, don't add anything |
| // as under XPath an empty default is indicated |
| // by no node. |
| |
| foundNSMatch = defaultNSFound || |
| (theNodeValue == DOMServices::s_emptyString); |
| defaultNSFound = true; |
| } |
| |
| for (NodeRefListBase::size_type lstIndex = 0; |
| foundNSMatch == false && lstIndex < nNSFound; |
| ++lstIndex) |
| { |
| if (subQueryResults.item(lstIndex)->getNodeName() == theNodeName) |
| { |
| foundNSMatch = true; |
| } |
| } |
| |
| if (foundNSMatch == false) |
| { |
| subQueryResults.addNode(attr); |
| ++nNSFound; |
| } |
| } |
| } |
| } |
| } |
| |
| theCurrentNode = theCurrentNode->getParentNode(); |
| } while (theCurrentNode != theOwnerDocument && theCurrentNode != 0); |
| } |
| |
| subQueryResults.reverse(); |
| |
| subQueryResults.setDocumentOrder(); |
| |
| return opPos + argLen; |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::findNodesOnUnknownAxis( |
| XPathExecutionContext& executionContext, |
| XalanNode* context, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType stepType, |
| MutableNodeRefList& /* subQueryResults */) const |
| { |
| const XPathExpression& currentExpression = getExpression(); |
| |
| const OpCodeMapValueType argLen = |
| currentExpression.getOpCodeArgumentLength(opPos); |
| |
| const GetCachedString theGuard1(executionContext); |
| const GetCachedString theGuard2(executionContext); |
| |
| executionContext.problem( |
| XPathExecutionContext::eXPath, |
| XPathExecutionContext::eError, |
| XalanMessageLoader::getMessage( |
| theGuard1.get(), |
| XalanMessages::UnknownAxis_1Param, |
| NumberToDOMString( |
| stepType, |
| theGuard2.get())), |
| getLocator(), |
| context); |
| |
| return opPos + argLen + 3; |
| } |
| |
| |
| |
| XPath::OpCodeMapPositionType |
| XPath::predicates( |
| XPathExecutionContext& executionContext, |
| OpCodeMapPositionType opPos, |
| MutableNodeRefList& subQueryResults) const |
| { |
| assert(&executionContext.getContextNodeList() == &subQueryResults); |
| |
| const XPathExpression& currentExpression = getExpression(); |
| |
| assert(currentExpression.getOpCodeMapValue(opPos) == XPathExpression::eOP_PREDICATE || |
| currentExpression.getOpCodeMapValue(opPos) == XPathExpression::eOP_PREDICATE_WITH_POSITION); |
| |
| NodeRefListBase::size_type theLength = subQueryResults.getLength(); |
| |
| for(;;) |
| { |
| // If we have no nodes left, then there's no point in executing any |
| // predicates. However, we will continue to loop, since we need to |
| // update endPredicatePos. |
| if (theLength > 0) |
| { |
| const OpCodeMapPositionType predOpPos = opPos + 2; |
| |
| // OK, this is a huge hack/optimization. If the predicate is |
| // simple a number, such as [2], we can just get the |
| // numeric value from the expression, and not bother executing |
| // the predicate. Furthermore, we don't need to execute the |
| // predicate for each node, since the evaluation is no dependent |
| // on the context node. All we really have to do is remove all |
| // nodes from subQueryResults, _except_ for the node at that |
| // position. The only trick is that XPath indexes from 1, while |
| // our node lists index from 0. |
| if (m_expression.getOpCodeMapValue(predOpPos) == XPathExpression::eOP_NUMBERLIT) |
| { |
| assert(m_expression.tokenQueueSize() > m_expression.getOpCodeMapValue(predOpPos + 3)); |
| |
| // Get the value of the number... |
| const double theIndex = |
| m_expression.getNumberLiteral(m_expression.getOpCodeMapValue(predOpPos + 2)); |
| |
| // If the index is out of range, or not an integer, just clear subQueryResults... |
| if (theIndex <= 0.0 || |
| NodeRefListBase::size_type(theIndex) > theLength || |
| double(NodeRefListBase::size_type(theIndex)) != theIndex) |
| { |
| subQueryResults.clear(); |
| } |
| else if (theLength > 1) |
| { |
| // Save the matching node... |
| XalanNode* const theNode = |
| subQueryResults.item(NodeRefListBase::size_type(theIndex) - 1); |
| |
| // Clear the list... |
| subQueryResults.clear(); |
| |
| // Add the node back in... |
| subQueryResults.addNode(theNode); |
| |
| subQueryResults.setDocumentOrder(); |
| } |
| else |
| { |
| // OK, if there's only 1 node in the list, then |
| // we don't need to bother modifying the list. |
| // Just assert that theIndex == 1.0... |
| assert(theIndex == 1.0); |
| } |
| } |
| else |
| { |
| for(NodeRefListBase::size_type i = 0; i < theLength; ++i) |
| { |
| XalanNode* const theNode = subQueryResults.item(i); |
| assert(theNode != 0); |
| |
| const XObjectPtr pred(predicate(theNode, opPos, executionContext)); |
| assert(pred.get() != 0); |
| |
| // Remove any node that doesn't satisfy the predicate. |
| if((XObject::eTypeNumber == pred->getType() && i + 1 != pred->num(executionContext)) || |
| pred->boolean(executionContext) == false) |
| { |
| // Set the node to 0. After we're done, |
| // we'll clear it out. |
| subQueryResults.setNode(i, 0); |
| } |
| } |
| |
| // Clear out any null entries... |
| subQueryResults.clearNulls(); |
| } |
| } |
| |
| opPos = currentExpression.getNextOpCodePosition(opPos); |
| |
| const OpCodeMapValueType nextStepType = currentExpression.getOpCodeMapValue(opPos); |
| |
| if (nextStepType != XPathExpression::eOP_PREDICATE && |
| nextStepType != XPathExpression::eOP_PREDICATE_WITH_POSITION) |
| { |
| break; |
| } |
| else |
| { |
| theLength = subQueryResults.getLength(); |
| } |
| } |
| |
| return opPos; |
| } |
| |
| |
| |
| XPath::NodeTester::NodeTester(const NodeTester& theSource) : |
| m_executionContext(theSource.m_executionContext), |
| m_targetNamespace(theSource.m_targetNamespace), |
| m_targetLocalName(theSource.m_targetLocalName), |
| m_testFunction(theSource.m_testFunction), |
| m_testFunction2(theSource.m_testFunction2) |
| { |
| } |
| |
| |
| |
| XPath::NodeTester::NodeTester( |
| const XPath& xpath, |
| XPathExecutionContext& executionContext, |
| OpCodeMapPositionType opPos, |
| OpCodeMapValueType argLen, |
| OpCodeMapValueType stepType) : |
| m_executionContext(&executionContext), |
| m_targetNamespace(0), |
| m_targetLocalName(0), |
| m_testFunction(0), |
| m_testFunction2(&NodeTester::testDefault2) |
| { |
| const XPathExpression& theExpression = xpath.getExpression(); |
| |
| switch(theExpression.getOpCodeMapValue(opPos)) |
| { |
| case XPathExpression::eNODETYPE_COMMENT: |
| m_testFunction = &NodeTester::testComment; |
| break; |
| |
| case XPathExpression::eNODETYPE_TEXT: |
| m_testFunction = &NodeTester::testText; |
| break; |
| |
| case XPathExpression::eNODETYPE_PI: |
| if (argLen == 1) |
| { |
| m_testFunction = &NodeTester::testPI; |
| } |
| else if(argLen == 2) |
| { |
| m_testFunction = &NodeTester::testPIName; |
| |
| m_targetLocalName = getStringFromTokenQueue( |
| theExpression, |
| opPos + 1); |
| } |
| else |
| { |
| GetCachedString theGuard(executionContext); |
| |
| executionContext.problem( |
| XPathExecutionContext::eXPath, |
| XPathExecutionContext::eError, |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::ArgLengthNodeTestIsIncorrect_1Param, |
| "processing-instruction()"), |
| xpath.getLocator(), |
| executionContext.getCurrentNode()); |
| } |
| break; |
| |
| case XPathExpression::eNODETYPE_NODE: |
| m_testFunction = &NodeTester::testNode; |
| break; |
| |
| case XPathExpression::eNODETYPE_ROOT: |
| m_testFunction = &NodeTester::testRoot; |
| break; |
| |
| case XPathExpression::eNODENAME: |
| { |
| bool isTotallyWild = false; |
| |
| m_targetNamespace = getStringFromTokenQueue( |
| theExpression, |
| opPos + 1); |
| |
| if (m_targetNamespace == 0 && |
| theExpression.getOpCodeMapValue(opPos + 2) == XPathExpression::eELEMWILDCARD) |
| { |
| isTotallyWild = true; |
| } |
| else |
| { |
| m_targetLocalName = getStringFromTokenQueue( |
| theExpression, |
| opPos + 2); |
| } |
| |
| if(stepType == XPathExpression::eFROM_ATTRIBUTES) |
| { |
| if (isTotallyWild == true) |
| { |
| m_testFunction = &NodeTester::testAttributeTotallyWild; |
| } |
| else if (m_targetNamespace == 0) |
| { |
| assert(m_targetLocalName != 0); |
| |
| m_testFunction = &NodeTester::testAttributeNCName; |
| } |
| else if (m_targetLocalName == 0) |
| { |
| assert(m_targetNamespace != 0); |
| |
| m_testFunction = &NodeTester::testAttributeNamespaceOnly; |
| } |
| else |
| { |
| assert(m_targetNamespace != 0 && m_targetLocalName != 0); |
| |
| |
| m_testFunction = &NodeTester::testAttributeQName; |
| } |
| } |
| else if (stepType == XPathExpression::eFROM_NAMESPACE) |
| { |
| if (isTotallyWild == true) |
| { |
| m_testFunction = &NodeTester::testNamespaceTotallyWild; |
| } |
| else |
| { |
| m_testFunction = &NodeTester::testNamespaceNCName; |
| } |
| } |
| else |
| { |
| if (isTotallyWild == true) |
| { |
| m_testFunction = &NodeTester::testElementTotallyWild; |
| } |
| else if (m_targetNamespace == 0) |
| { |
| m_testFunction = &NodeTester::testElementNCName; |
| } |
| else if (m_targetLocalName == 0) |
| { |
| assert(m_targetNamespace != 0); |
| |
| m_testFunction = &NodeTester::testElementNamespaceOnly; |
| } |
| else |
| { |
| assert(m_targetNamespace != 0 && m_targetLocalName != 0); |
| |
| m_testFunction = &NodeTester::testElementQName; |
| } |
| } |
| } |
| break; |
| |
| default: |
| m_testFunction = &NodeTester::testDefault; |
| break; |
| } |
| |
| assert(m_testFunction != 0); |
| } |
| |
| |
| |
| XPath::NodeTester::NodeTester() : |
| m_executionContext(0), |
| m_targetNamespace(0), |
| m_targetLocalName(0), |
| m_testFunction(&NodeTester::testDefault), |
| m_testFunction2(&NodeTester::testDefault2) |
| { |
| } |
| |
| |
| |
| XPath::NodeTester::NodeTester( |
| XPathConstructionContext& theConstructionContext, |
| const XalanDOMString& theNameTest, |
| const PrefixResolver& thePrefixResolver, |
| const Locator* theLocator, |
| eMatchScore* theMatchScore) : |
| m_executionContext(0), |
| m_targetNamespace(0), |
| m_targetLocalName(0), |
| m_testFunction(&NodeTester::testDefault), |
| m_testFunction2(&NodeTester::testDefault2) |
| { |
| const eMatchScore theScore = |
| initialize( |
| theConstructionContext, |
| theNameTest, |
| thePrefixResolver, |
| theLocator); |
| |
| if (theMatchScore != 0) |
| { |
| *theMatchScore = theScore; |
| } |
| } |
| |
| |
| |
| XPath::NodeTester::NodeTester( |
| const XalanDOMString& theNamespaceURI, |
| const XalanDOMString& theLocalName, |
| eMatchScore* theMatchScore) : |
| m_executionContext(0), |
| m_targetNamespace(0), |
| m_targetLocalName(0), |
| m_testFunction(&NodeTester::testDefault), |
| m_testFunction2(0) |
| { |
| const eMatchScore theScore = |
| initialize(theNamespaceURI, theLocalName); |
| |
| if (theMatchScore != 0) |
| { |
| *theMatchScore = theScore; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::initialize( |
| XPathConstructionContext& theConstructionContext, |
| const XalanDOMString& theNameTest, |
| const PrefixResolver& thePrefixResolver, |
| const Locator* theLocator) |
| { |
| const XalanDOMString::size_type theLength = |
| theNameTest.length(); |
| |
| if (theLength == 1 && theNameTest[0] == XPath::PSEUDONAME_ANY[0]) |
| { |
| return initialize(s_emptyString, s_emptyString); |
| } |
| else |
| { |
| eMatchScore theResult = eMatchScoreNone; |
| |
| const XalanDOMString::size_type theIndex = |
| indexOf(theNameTest, XalanUnicode::charColon); |
| |
| // If there's no ':', it's an NCName... |
| if (theIndex == theLength) |
| { |
| if (XalanQName::isValidNCName(theNameTest) == false) |
| { |
| const XPathConstructionContext::GetCachedString theGuard(theConstructionContext); |
| |
| theConstructionContext.problem( |
| XPathConstructionContext::eXPath, |
| XPathConstructionContext::eError, |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::IsNotValidQName_1Param, |
| theNameTest), |
| theLocator, |
| 0); |
| } |
| else |
| { |
| theResult = initialize( |
| s_emptyString, |
| theConstructionContext.getPooledString(theNameTest)); |
| } |
| } |
| else |
| { |
| const XPathConstructionContext::GetCachedString scratchGuard(theConstructionContext); |
| |
| XalanDOMString& theScratchString = scratchGuard.get(); |
| |
| theScratchString.assign(theNameTest, 0, theIndex); |
| |
| // Get the namespace URI for the prefix... |
| const XalanDOMString* const theNamespaceURI = |
| thePrefixResolver.getNamespaceForPrefix(theScratchString); |
| |
| if (theNamespaceURI == 0) |
| { |
| theConstructionContext.problem( |
| XPathConstructionContext::eXPath, |
| XPathConstructionContext::eError, |
| XalanMessageLoader::getMessage( |
| theScratchString, |
| XalanMessages::PrefixIsNotDeclared_1Param), |
| theLocator, |
| 0); |
| } |
| else |
| { |
| // OK, now we have a namespace URI... |
| if (XalanQName::isValidNCName(theScratchString) == false) |
| { |
| theConstructionContext.problem( |
| XPathConstructionContext::eXPath, |
| XPathConstructionContext::eError, |
| XalanMessageLoader::getMessage( |
| theScratchString, |
| XalanMessages::IsNotValidQName_1Param, |
| theNameTest), |
| theLocator, |
| 0); |
| } |
| else if (theIndex == theLength - 2 && |
| theNameTest[theIndex + 1] == XPath::PSEUDONAME_ANY[0]) |
| { |
| // It's of the form "NCName:*" |
| theResult = initialize( |
| theConstructionContext.getPooledString(*theNamespaceURI), |
| s_emptyString); |
| } |
| else |
| { |
| theScratchString.assign(theNameTest, theIndex + 1, theLength - theIndex - 1); |
| |
| if (XalanQName::isValidNCName(theScratchString) == false) |
| { |
| theConstructionContext.problem( |
| XPathConstructionContext::eXPath, |
| XPathConstructionContext::eError, |
| XalanMessageLoader::getMessage( |
| theScratchString, |
| XalanMessages::IsNotValidQName_1Param, |
| theNameTest), |
| theLocator, |
| 0); |
| } |
| else |
| { |
| // It's of the form "NCName:NCName" |
| theResult = initialize( |
| theConstructionContext.getPooledString(*theNamespaceURI), |
| theConstructionContext.getPooledString(theScratchString)); |
| } |
| } |
| } |
| } |
| |
| return theResult; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::initialize( |
| const XalanDOMString& theNamespaceURI, |
| const XalanDOMString& theLocalName) |
| { |
| if (theNamespaceURI.empty() == false) |
| { |
| m_targetNamespace = &theNamespaceURI; |
| |
| if (theLocalName.empty() == true) |
| { |
| m_testFunction2 = &NodeTester::testElementNamespaceOnly2; |
| |
| return eMatchScoreNSWild; |
| } |
| else |
| { |
| m_testFunction2 = &NodeTester::testElementQName2; |
| |
| m_targetLocalName = &theLocalName; |
| |
| return eMatchScoreQName; |
| } |
| } |
| else if (theLocalName.empty() == false) |
| { |
| m_testFunction2 = &NodeTester::testElementNCName2; |
| |
| m_targetLocalName = &theLocalName; |
| |
| return eMatchScoreQName; |
| } |
| else |
| { |
| m_testFunction2 = &NodeTester::testElementTotallyWild2; |
| |
| return eMatchScoreNodeTest; |
| } |
| } |
| |
| |
| |
| inline bool |
| isNamespaceDeclaration(const XalanNode& theAttributeNode) |
| { |
| assert(theAttributeNode.getNodeType() == XalanNode::ATTRIBUTE_NODE); |
| |
| return DOMServices::isNamespaceDeclaration(static_cast<const XalanAttr&>(theAttributeNode)); |
| } |
| |
| |
| |
| // MSVC 6 generates some really horrible code for some of these very simple functions when they're inlined... |
| #if defined(_MSC_VER) && _MSC_VER <= 1300 && !defined(__INTEL_COMPILER) |
| #pragma auto_inline(off) |
| #endif |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testComment( |
| const XalanNode& /* context */, |
| XalanNode::NodeType nodeType) const |
| { |
| if (XalanNode::COMMENT_NODE == nodeType) |
| { |
| return eMatchScoreNodeTest; |
| } |
| else |
| { |
| return eMatchScoreNone; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testText( |
| const XalanNode& context, |
| XalanNode::NodeType nodeType) const |
| { |
| if (XalanNode::TEXT_NODE == nodeType && |
| shouldStripSourceNode(static_cast<const XalanText&>(context)) == false) |
| { |
| return eMatchScoreNodeTest; |
| } |
| else |
| { |
| return eMatchScoreNone; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testPI( |
| const XalanNode& /* context */, |
| XalanNode::NodeType nodeType) const |
| { |
| if (XalanNode::PROCESSING_INSTRUCTION_NODE == nodeType) |
| { |
| return eMatchScoreNodeTest; |
| } |
| else |
| { |
| return eMatchScoreNone; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testPIName( |
| const XalanNode& context, |
| XalanNode::NodeType nodeType) const |
| { |
| assert(m_targetLocalName != 0); |
| |
| if (XalanNode::PROCESSING_INSTRUCTION_NODE == nodeType && |
| context.getNodeName() == *m_targetLocalName) |
| { |
| return eMatchScoreQName; |
| } |
| else |
| { |
| return eMatchScoreNone; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testNode( |
| const XalanNode& context, |
| XalanNode::NodeType nodeType) const |
| { |
| if (nodeType != XalanNode::TEXT_NODE || |
| shouldStripSourceNode(static_cast<const XalanText&>(context)) == false) |
| { |
| return eMatchScoreNodeTest; |
| } |
| else |
| { |
| return eMatchScoreNone; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testRoot( |
| const XalanNode& /* context */, |
| XalanNode::NodeType nodeType) const |
| { |
| if (XalanNode::DOCUMENT_NODE == nodeType || |
| XalanNode::DOCUMENT_FRAGMENT_NODE == nodeType) |
| { |
| return eMatchScoreOther; |
| } |
| else |
| { |
| return eMatchScoreNone; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testAttributeNCName( |
| const XalanNode& context, |
| XalanNode::NodeType nodeType) const |
| { |
| assert(m_targetNamespace == 0 && m_targetLocalName != 0); |
| |
| if (XalanNode::ATTRIBUTE_NODE != nodeType || |
| isNamespaceDeclaration(context) == true || |
| matchLocalName(context) == false) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreQName; |
| } |
| } |
| |
| inline bool |
| XPath::NodeTester::matchLocalNameAndNamespaceURI(const XalanNode& context) const |
| { |
| assert(m_targetNamespace != 0 && m_targetLocalName != 0); |
| |
| return DOMServices::getLocalNameOfNode(context) == *m_targetLocalName && |
| context.getNamespaceURI() == *m_targetNamespace; |
| } |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testAttributeQName( |
| const XalanNode& context, |
| XalanNode::NodeType nodeType) const |
| { |
| assert(m_targetNamespace != 0 && m_targetLocalName != 0); |
| |
| if (XalanNode::ATTRIBUTE_NODE != nodeType || |
| isNamespaceDeclaration(context) == true || |
| matchLocalNameAndNamespaceURI(context) == false) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreQName; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testAttributeNamespaceOnly( |
| const XalanNode& context, |
| XalanNode::NodeType nodeType) const |
| { |
| assert(m_targetNamespace != 0 && m_targetLocalName == 0); |
| |
| if (XalanNode::ATTRIBUTE_NODE != nodeType || |
| isNamespaceDeclaration(context) == true || |
| matchNamespaceURI(context) == false) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreNSWild; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testAttributeTotallyWild( |
| const XalanNode& context, |
| XalanNode::NodeType nodeType) const |
| { |
| if (XalanNode::ATTRIBUTE_NODE != nodeType || |
| isNamespaceDeclaration(context) == true) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreNodeTest; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testElementNCName( |
| const XalanNode& context, |
| XalanNode::NodeType nodeType) const |
| { |
| assert(m_targetNamespace == 0 && m_targetLocalName != 0); |
| |
| if (XalanNode::ELEMENT_NODE != nodeType || |
| matchLocalName(context) == false) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreQName; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testElementQName( |
| const XalanNode& context, |
| XalanNode::NodeType nodeType) const |
| { |
| assert(m_targetNamespace != 0 && m_targetLocalName != 0); |
| |
| if (XalanNode::ELEMENT_NODE != nodeType || |
| matchLocalNameAndNamespaceURI(context) == false) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreQName; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testElementNamespaceOnly( |
| const XalanNode& context, |
| XalanNode::NodeType nodeType) const |
| { |
| assert(m_targetNamespace != 0 && m_targetLocalName == 0); |
| |
| if (XalanNode::ELEMENT_NODE != nodeType || |
| matchNamespaceURI(context) == false) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreNSWild; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testElementTotallyWild( |
| const XalanNode& /* context */, |
| XalanNode::NodeType nodeType) const |
| { |
| assert(m_targetNamespace == 0 && m_targetLocalName == 0); |
| |
| if (XalanNode::ELEMENT_NODE != nodeType) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreNodeTest; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testElementNCName2(const XalanElement& context) const |
| { |
| assert( |
| m_targetNamespace == 0 && |
| m_targetLocalName != 0); |
| |
| if (matchLocalName(context) == false) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreQName; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testElementQName2(const XalanElement& context) const |
| { |
| assert( |
| m_targetNamespace != 0 && |
| m_targetLocalName != 0); |
| |
| if (matchLocalNameAndNamespaceURI(context) == false) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreQName; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testElementNamespaceOnly2(const XalanElement& context) const |
| { |
| assert( |
| m_targetNamespace != 0 && |
| m_targetLocalName == 0); |
| |
| if (matchNamespaceURI(context) == false) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreNSWild; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testElementTotallyWild2(const XalanElement& /* context */) const |
| { |
| assert( |
| m_targetNamespace == 0 && |
| m_targetLocalName == 0); |
| |
| return eMatchScoreNodeTest; |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testNamespaceNCName( |
| const XalanNode& context, |
| XalanNode::NodeType nodeType) const |
| { |
| assert(m_targetNamespace == 0 && m_targetLocalName != 0); |
| |
| if (XalanNode::ATTRIBUTE_NODE != nodeType || |
| isNamespaceDeclaration(context) == false || |
| matchNamespace(context) == false) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreQName; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testNamespaceTotallyWild( |
| const XalanNode& context, |
| XalanNode::NodeType nodeType) const |
| { |
| assert(m_targetNamespace == 0 && m_targetLocalName == 0); |
| |
| if (XalanNode::ATTRIBUTE_NODE != nodeType || |
| isNamespaceDeclaration(context) == false) |
| { |
| return eMatchScoreNone; |
| } |
| else |
| { |
| return eMatchScoreNodeTest; |
| } |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testDefault( |
| const XalanNode& /* context */, |
| XalanNode::NodeType /* nodeType */) const |
| { |
| return eMatchScoreNone; |
| } |
| |
| |
| |
| XPath::eMatchScore |
| XPath::NodeTester::testDefault2(const XalanElement& /* context */) const |
| { |
| return eMatchScoreNone; |
| } |
| |
| |
| |
| bool |
| XPath::NodeTester::matchLocalName(const XalanNode& context) const |
| { |
| assert(m_targetLocalName != 0); |
| |
| return context.getNamespaceURI().empty() == true && |
| DOMServices::getLocalNameOfNode(context) == *m_targetLocalName; |
| } |
| |
| |
| |
| bool |
| XPath::NodeTester::matchNamespaceURI(const XalanNode& context) const |
| { |
| assert(m_targetNamespace != 0); |
| |
| return context.getNamespaceURI() == *m_targetNamespace; |
| } |
| |
| |
| bool |
| XPath::NodeTester::matchNamespace(const XalanNode& context) const |
| { |
| assert(m_targetLocalName != 0); |
| |
| return context.getLocalName() == *m_targetLocalName; |
| } |
| |
| |
| |
| bool |
| XPath::NodeTester::shouldStripSourceNode(const XalanText& context) const |
| { |
| assert(m_executionContext != 0); |
| |
| return m_executionContext->shouldStripSourceNode(context); |
| } |
| |
| |
| |
| const XalanDOMChar XPath::PSEUDONAME_ANY[] = |
| { |
| XalanUnicode::charAsterisk, |
| 0 |
| }; |
| |
| const XalanDOMChar XPath::PSEUDONAME_ROOT[] = |
| { |
| XalanUnicode::charSolidus, |
| 0 |
| }; |
| |
| const XalanDOMChar XPath::PSEUDONAME_TEXT[] = |
| { |
| XalanUnicode::charNumberSign, |
| XalanUnicode::charLetter_t, |
| XalanUnicode::charLetter_e, |
| XalanUnicode::charLetter_x, |
| XalanUnicode::charLetter_t, |
| 0 |
| }; |
| |
| const XalanDOMChar XPath::PSEUDONAME_COMMENT[] = |
| { |
| XalanUnicode::charNumberSign, |
| XalanUnicode::charLetter_c, |
| XalanUnicode::charLetter_o, |
| XalanUnicode::charLetter_m, |
| XalanUnicode::charLetter_m, |
| XalanUnicode::charLetter_e, |
| XalanUnicode::charLetter_n, |
| XalanUnicode::charLetter_t, |
| 0 |
| }; |
| |
| const XalanDOMChar XPath::PSEUDONAME_PI[] = |
| { |
| XalanUnicode::charNumberSign, |
| XalanUnicode::charLetter_p, |
| XalanUnicode::charLetter_i, |
| 0 |
| }; |
| |
| const XalanDOMChar XPath::PSEUDONAME_OTHER[] = |
| { |
| XalanUnicode::charAsterisk, |
| 0 |
| }; |
| |
| const XalanDOMChar XPath::PSEUDONAME_NODE[] = |
| { |
| XalanUnicode::charNumberSign, |
| XalanUnicode::charLetter_n, |
| XalanUnicode::charLetter_o, |
| XalanUnicode::charLetter_d, |
| XalanUnicode::charLetter_e, |
| 0 |
| }; |
| |
| |
| |
| // Don't auto-create the table... |
| |
| XPath::FunctionTableType XPath::s_functions(false); |
| |
| |
| |
| void |
| XPath::initialize(MemoryManager& theManager) |
| { |
| s_functions.setMemoryManager(theManager); |
| |
| s_functions.CreateTable(); |
| } |
| |
| |
| |
| void |
| XPath::terminate() |
| { |
| s_functions.DestroyTable(); |
| } |
| |
| |
| |
| } |