/* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed 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 #include #include #include #include #include #include #include #include "FormatterStringLengthCounter.hpp" #include "MutableNodeRefList.hpp" #include "XalanQNameByReference.hpp" #include "XObject.hpp" #include "XObjectFactory.hpp" #include "XPathConstructionContext.hpp" #include "XPathEnvSupport.hpp" XALAN_CPP_NAMESPACE_BEGIN const XalanDOMString XPath::s_emptyString(XalanMemMgrs::getDummyMemMgr()); XPath::XPath(MemoryManagerType& theManager, const LocatorType* theLocator) : m_expression(theManager), m_locator(theLocator), m_inStylesheet(false) { } XPath* XPath::create(MemoryManagerType& theManager, const LocatorType* theLocator) { typedef XPath Type; XalanMemMgrAutoPtr theGuard( theManager , (Type*)theManager.allocate(sizeof(Type))); Type* theResult = theGuard.get(); new (theResult) Type(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(); LongToDOMString( m_expression.getOpCodeMapValue(opPos), theOpCode); const GetCachedString theGuard2(executionContext); executionContext.error( XalanMessageLoader::getMessage( theGuard2.get(), XalanMessages::InvalidOpcodeWasDetected_1Param, theOpCode), context, m_locator); } void XPath::notNodeSetError( XalanNode* context, XPathExecutionContext& executionContext) const { GetCachedString theGuard(executionContext); XalanDOMString& theBuffer = theGuard.get(); executionContext.error( XalanMessageLoader::getMessage( theBuffer, XalanMessages::ExpressionDoesNotEvaluateToNodeSet), context, m_locator); } 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)); 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(); 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(); break; case XPathExpression::eOP_FUNCTION: result = runFunction(context, opPos, executionContext)->boolean(); 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)); 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(); 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(); break; case XPathExpression::eOP_FUNCTION: result = runFunction(context, opPos, executionContext)->num(); 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); 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(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(result); break; case XPathExpression::eOP_FUNCTION: runFunction(context, opPos, executionContext)->str(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), 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( 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( formatterListener, function); break; case XPathExpression::eOP_FUNCTION: runFunction(context, opPos, executionContext)->str(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), 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.error( XalanMessageLoader::getMessage( theBuffer, XalanMessages::CannotEvaluateXPathExpressionAsMatchPattern), node, m_locator); } 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 XObject* 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, 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, 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); theLiteral->str(theString); } 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); theLiteral->str(theString); } 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(), 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, 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)); if (nodesetResult.null() == false) { return nodesetResult->nodeset().getLength(); } else { return result->getLength(); } } 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) const { assert(context != 0); FormatterStringLengthCounter theCounter; DOMServices::getNodeData(*context, theCounter, &FormatterListener::characters); return theCounter.getCount(); } double XPath::functionStringLength( XalanNode* context, OpCodeMapPositionType opPos, XPathExecutionContext& executionContext) const { assert(context != 0); FormatterStringLengthCounter theCounter; executeMore(context, opPos + 2, executionContext, theCounter, &FormatterListener::characters); return theCounter.getCount(); } 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 XPathExecutionContext::GetAndReleaseCachedString theData(executionContext); XalanDOMString& theString = theData.get(); for (NodeRefListBase::size_type i = 0; i < theLength; i++) { DOMServices::getNodeData(*theNodeList->item(i), theString); sum = DoubleSupport::add(sum, DoubleSupport::toDouble(theString, executionContext.getMemoryManager())); clear(theString); } } 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(); } else if (subQueryResults->getReverseDocumentOrder() == true) { queryResults.swap(*subQueryResults); queryResults.reverse(); } else { assert(subQueryResults->getDocumentOrder() == true); queryResults.swap(*subQueryResults); } } } 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); 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()); assert(score == nodeTest(executionContext, context, context->getNodeType(), opPos, argLen, stepType)); 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()); assert(score == nodeTest( executionContext, context, context->getNodeType(), opPos, argLen, XPathExpression::eFROM_ATTRIBUTES)); } break; case XPathExpression::eMATCH_ANY_ANCESTOR: case XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE: { 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); assert(score == nodeTest(executionContext, context, nodeType, opPos, argLen, stepType)); 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); assert(score == nodeTest( executionContext, context, nodeType, opPos, argLen, XPathExpression::eMATCH_IMMEDIATE_ANCESTOR)); } } break; default: { const GetCachedString theGuard1(executionContext); const GetCachedString theGuard2(executionContext); executionContext.error( XalanMessageLoader::getMessage( theGuard1.get(), XalanMessages::UnknownMatchOpCode_1Param, LongToDOMString( stepType, theGuard2.get())), context, getLocator()); break; } } opPos += argLen; nextStepType = currentExpression.getOpCodeMapValue(opPos); if(score != eMatchScoreNone && (XPathExpression::eOP_PREDICATE == nextStepType || XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType)) { score = eMatchScoreOther; while(XPathExpression::eOP_PREDICATE == nextStepType || XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType) { // 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() == false) { score = eMatchScoreNone; break; } } opPos = currentExpression.getNextOpCodePosition(opPos); nextStepType = currentExpression.getOpCodeMapValue(opPos); } } 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 defined(XALAN_OLD_STYLE_CASTS) if (((const XalanDocument*)docContext)->getDocumentElement() == 0) #else if (static_cast(docContext)->getDocumentElement() == 0) #endif { 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()); assert(score == nodeTest(executionContext, theParent, theParent->getNodeType(), opPos, argLen, stepType)); 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()); assert(score == nodeTest(executionContext, context, context->getNodeType(), opPos, argLen, stepType)); 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()); assert(score == nodeTest(executionContext, context, context->getNodeType(), opPos, argLen, stepType)); 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()); assert(score == nodeTest(executionContext, context, context->getNodeType(), opPos, argLen, stepType)); 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 unsigned int nAttrs = attributeList->getLength(); if (nAttrs != 0) { const NodeTester theTester( *this, executionContext, opPos, argLen, stepType); for(unsigned int 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); assert(score == nodeTest(executionContext, theNode, XalanNode::ATTRIBUTE_NODE, opPos, argLen, stepType)); 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()); assert(score == nodeTest(executionContext, child, child->getNodeType(), opPos, argLen, stepType)); 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()); assert(score == nodeTest(executionContext, pos, pos->getNodeType(), opPos, argLen, stepType)); 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()); assert(score == nodeTest(executionContext, pos, pos->getNodeType(), opPos, argLen, stepType)); 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()); assert(score == nodeTest(executionContext, pos, pos->getNodeType(), opPos, argLen, stepType)); 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()); assert(score == nodeTest(executionContext, pos, pos->getNodeType(), opPos, argLen, stepType)); 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()); assert(score == nodeTest(executionContext, pos, pos->getNodeType(), opPos, argLen, stepType)); 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()); assert(score == nodeTest(executionContext, pos, pos->getNodeType(), opPos, argLen, stepType)); 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) { unsigned int 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 nodeTest(). if (startsWith(theNodeName, DOMServices::s_XMLNamespaceWithSeparator) == true || theNodeName == DOMServices::s_XMLNamespace) { const eMatchScore score = theTester(*attr, XalanNode::ATTRIBUTE_NODE); assert(score == nodeTest(executionContext, attr, XalanNode::ATTRIBUTE_NODE, opPos, argLen, stepType)); 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.error( XalanMessageLoader::getMessage( theGuard1.get(), XalanMessages::UnknownAxis_1Param, LongToDOMString( stepType, theGuard2.get())), context, getLocator()); return opPos + argLen + 3; } #if !defined(NDEBUG) XPath::eMatchScore XPath::nodeTest( XPathExecutionContext& executionContext, XalanNode* context, XalanNode::NodeType nodeType, OpCodeMapPositionType opPos, OpCodeMapValueType argLen, OpCodeMapValueType stepType) const { assert(context->getNodeType() == nodeType); const XPathExpression& currentExpression = getExpression(); eMatchScore score = eMatchScoreNone; const OpCodeMapValueType testType = currentExpression.getOpCodeMapValue(opPos); switch(testType) { case XPathExpression::eNODETYPE_COMMENT: if (XalanNode::COMMENT_NODE == nodeType) { score = eMatchScoreNodeTest; } break; case XPathExpression::eNODETYPE_TEXT: if ((XalanNode::CDATA_SECTION_NODE == nodeType || XalanNode::TEXT_NODE == nodeType) && #if defined(XALAN_OLD_STYLE_CASTS) executionContext.shouldStripSourceNode((const XalanText&)*context) == false) #else executionContext.shouldStripSourceNode(static_cast(*context)) == false) #endif { score = eMatchScoreNodeTest; } break; case XPathExpression::eNODETYPE_PI: if(XalanNode::PROCESSING_INSTRUCTION_NODE == nodeType) { if(argLen == 1) { score = eMatchScoreNodeTest; } else if(argLen == 2) { opPos++; const OpCodeMapValueType tokenPosition = currentExpression.getOpCodeMapValue(opPos); const XObject* const name = currentExpression.getToken(tokenPosition); assert(name != 0); if (context->getNodeName() == name->str()) { score = eMatchScoreQName; } } else { XalanDOMString theBuffer(executionContext.getMemoryManager()); executionContext.error( XalanMessageLoader::getMessage( theBuffer, XalanMessages::ArgLengthNodeTestIsIncorrect_1Param, "processing-instruction()"), context, getLocator()); } } break; case XPathExpression::eNODETYPE_NODE: if (nodeType == XalanNode::CDATA_SECTION_NODE || nodeType == XalanNode::TEXT_NODE) { #if defined(XALAN_OLD_STYLE_CASTS) if (executionContext.shouldStripSourceNode((const XalanText&)*context) == false) #else if (executionContext.shouldStripSourceNode(static_cast(*context)) == false) #endif { score = eMatchScoreNodeTest; } } else { score = eMatchScoreNodeTest; } break; case XPathExpression::eNODETYPE_ROOT: if (XalanNode::DOCUMENT_FRAGMENT_NODE == nodeType || XalanNode::DOCUMENT_NODE == nodeType) { score = eMatchScoreOther; } break; case XPathExpression::eNODENAME: { opPos++; if (nodeType == XalanNode::ATTRIBUTE_NODE || nodeType == XalanNode::ELEMENT_NODE) { bool test = false; OpCodeMapValueType queueIndex = currentExpression.getOpCodeMapValue(opPos); assert(queueIndex == XPathExpression::eEMPTY || queueIndex < currentExpression.tokenQueueSize()); const XalanDOMString& targetNS = queueIndex != XPathExpression::eEMPTY ? currentExpression.getToken(queueIndex)->str() : s_emptyString; opPos++; // From the draft: "Two expanded names are equal if they // have the same local part, and either both have no URI or // both have the same URI." // "A node test * is true for any node of the principal node type. // For example, child::* will select all element children of the // context node, and attribute::* will select all attributes of // the context node." // "A node test can have the form NCName:*. In this case, the prefix // is expanded in the same way as with a QName using the context // namespace declarations. The node test will be true for any node // of the principal type whose expanded name has the URI to which // the prefix expands, regardless of the local part of the name." const bool isTotallyWild = 0 == length(targetNS) && currentExpression.getOpCodeMapValue(opPos) == XPathExpression::eELEMWILDCARD; bool didMatchNS = false; if(isTotallyWild == false) { const XalanDOMString& contextNS = DOMServices::getNamespaceOfNode(*context); if(0 != length(targetNS) && 0 != length(contextNS)) { test = contextNS == targetNS; didMatchNS = true; } else { test = XPathExpression::eELEMWILDCARD == queueIndex || (0 == length(contextNS) && 0 == length(targetNS)); } } else { test = true; } queueIndex = currentExpression.getOpCodeMapValue(opPos); if(test == true) { switch(nodeType) { case XalanNode::ATTRIBUTE_NODE: if(stepType == XPathExpression::eFROM_ATTRIBUTES || stepType == XPathExpression::eFROM_NAMESPACE) { assert(context->getNodeType() == XalanNode::ATTRIBUTE_NODE); const XalanDOMString& attrName = context->getNodeName(); const bool isNamespace = startsWith(attrName, DOMServices::s_XMLNamespaceWithSeparator) || attrName == DOMServices::s_XMLNamespace; if(XPathExpression::eELEMWILDCARD == queueIndex) { if(stepType == XPathExpression::eFROM_ATTRIBUTES) { if (isNamespace == false) { if (isTotallyWild == true) { score = eMatchScoreNodeTest; } else { score = eMatchScoreNSWild; } } } else { if (isNamespace == true) { score = eMatchScoreNodeTest; } } } else { if(stepType == XPathExpression::eFROM_ATTRIBUTES) { if (isNamespace == false) { assert(queueIndex >= 0); const XalanDOMString& targetLocalName = currentExpression.getToken(queueIndex)->str(); const XalanDOMString& localAttrName = DOMServices::getLocalNameOfNode(*context); if (localAttrName == targetLocalName) { score = eMatchScoreQName; } } } else { if (isNamespace == true) { const XalanAttr* const theAttrNode = #if defined(XALAN_OLD_STYLE_CASTS) (const XalanAttr*)context; #else static_cast(context); #endif assert(theAttrNode != 0); const XalanDOMString& theNamespace = theAttrNode->getLocalName(); assert(queueIndex >= 0); const XalanDOMString& targetLocalName = currentExpression.getToken(queueIndex)->str(); if (theNamespace == targetLocalName) { score = eMatchScoreQName; } } } } } break; case XalanNode::ELEMENT_NODE: if(stepType != XPathExpression::eFROM_ATTRIBUTES) { if(XPathExpression::eELEMWILDCARD == queueIndex) { score = didMatchNS == true ? eMatchScoreNSWild : eMatchScoreNodeTest; } else { assert(queueIndex >= 0); const XalanDOMString& targetLocalName = currentExpression.getToken(queueIndex)->str(); if (DOMServices::getLocalNameOfNode(*context) == targetLocalName) { score = eMatchScoreQName; } } } break; default: // Trying to match on anything else causes nasty bugs. break; } // end switch(nodeType) } // end if(test) } // end if (nodeType == XalanNode::ATTRIBUTE_NODE || nodeType == XalanNode::ELEMENT_NODE) } // end case XPathExpression::eNODENAME break; default: break; } // end switch(testType) return score; } #endif // !defined(NDEBUG) 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()) || pred->boolean() == 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.error( XalanMessageLoader::getMessage( theGuard.get(), XalanMessages::ArgLengthNodeTestIsIncorrect_1Param, "processing-instruction()"), 0, xpath.getLocator()); } 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 LocatorType* 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 LocatorType* theLocator) { const XalanDOMString::size_type theLength = length(theNameTest); 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::GetAndReleaseCachedString theGuard(theConstructionContext); theConstructionContext.error( XalanMessageLoader::getMessage( theGuard.get(), XalanMessages::IsNotValidQName_1Param, theNameTest), 0, theLocator); } else { theResult = initialize( s_emptyString, theConstructionContext.getPooledString(theNameTest)); } } else { const XPathConstructionContext::GetAndReleaseCachedString 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.error( XalanMessageLoader::getMessage( theScratchString, XalanMessages::PrefixIsNotDeclared_1Param), 0, theLocator); } else { // OK, now we have a namespace URI... if (XalanQName::isValidNCName(theScratchString) == false) { theConstructionContext.error( XalanMessageLoader::getMessage( theScratchString, XalanMessages::IsNotValidQName_1Param, theNameTest), 0, theLocator); } 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.error( XalanMessageLoader::getMessage( theScratchString, XalanMessages::IsNotValidQName_1Param, theNameTest), 0, theLocator); } 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); #if defined(XALAN_OLD_STYLE_CASTS) return DOMServices::isNamespaceDeclaration((const XalanAttr&)theAttributeNode); #else return DOMServices::isNamespaceDeclaration(static_cast(theAttributeNode)); #endif } // MSVC 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 || XalanNode::CDATA_SECTION_NODE == nodeType) && #if defined(XALAN_OLD_STYLE_CASTS) shouldStripSourceNode((const XalanText&)context) == false) #else shouldStripSourceNode(static_cast(context)) == false) #endif { 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 && nodeType != XalanNode::CDATA_SECTION_NODE) || #if defined(XALAN_OLD_STYLE_CASTS) shouldStripSourceNode((const XalanText&)context) == false) #else shouldStripSourceNode(static_cast(context)) == false) #endif { 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 length(context.getNamespaceURI()) == 0 && 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(MemoryManagerType& theManager) { s_functions.setMemoryManager(theManager); s_functions.CreateTable(); } void XPath::terminate() { s_functions.DestroyTable(); } XALAN_CPP_NAMESPACE_END