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