Bug 205703: Refcount Expr-results, to avoid cloning, and recycle them, to avoid memorymanagement.

r=Pike sr=peterv
This commit is contained in:
sicking%bigfoot.com 2005-11-02 07:40:48 +00:00
Родитель f69a5761ff
Коммит c0f7dd27f1
67 изменённых файлов: 1836 добавлений и 1132 удалений

Просмотреть файл

@ -87,4 +87,7 @@
#define NS_ERROR_XSLT_LOAD_RECURSION \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 12)
#define NS_ERROR_XPATH_BAD_ARGUMENT_COUNT \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XSLT, 13)
#endif // __TX_ERROR

Просмотреть файл

@ -55,20 +55,20 @@ CPPSRCS = AdditiveExpr.cpp \
MultiplicativeExpr.cpp \
NodeSet.cpp \
NodeSetFunctionCall.cpp \
NumberExpr.cpp \
NumberFunctionCall.cpp \
NumberResult.cpp \
PathExpr.cpp \
PredicateList.cpp \
RelationalExpr.cpp \
RootExpr.cpp \
StringExpr.cpp \
StringFunctionCall.cpp \
StringResult.cpp \
txLiteralExpr.cpp \
txNameTest.cpp \
txNodeTypeTest.cpp \
txForwardContext.cpp \
txNodeSetContext.cpp \
txResultRecycler.cpp \
UnionExpr.cpp \
UnaryExpr.cpp \
VariableRefExpr.cpp

Просмотреть файл

@ -76,6 +76,17 @@ nsXPathEvaluator::CreateExpression(const nsAString & aExpression,
nsIDOMXPathNSResolver *aResolver,
nsIDOMXPathExpression **aResult)
{
nsresult rv = NS_OK;
if (!mRecycler) {
nsRefPtr<txResultRecycler> recycler = new txResultRecycler;
NS_ENSURE_TRUE(recycler, NS_ERROR_OUT_OF_MEMORY);
rv = recycler->init();
NS_ENSURE_SUCCESS(rv, rv);
mRecycler = recycler;
}
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
ParseContextImpl pContext(aResolver, !doc || doc->IsCaseSensitive());
Expr* expression = ExprParser::createExpr(PromiseFlatString(aExpression),
@ -83,7 +94,7 @@ nsXPathEvaluator::CreateExpression(const nsAString & aExpression,
if (!expression)
return NS_ERROR_DOM_INVALID_EXPRESSION_ERR;
*aResult = new nsXPathExpression(expression);
*aResult = new nsXPathExpression(expression, mRecycler);
if (!*aResult) {
delete expression;
return NS_ERROR_OUT_OF_MEMORY;

Просмотреть файл

@ -44,6 +44,8 @@
#include "txIXPathContext.h"
#include "nsIXPathEvaluatorInternal.h"
#include "nsIWeakReference.h"
#include "nsAutoPtr.h"
#include "txResultRecycler.h"
class nsIDOMDocument;
@ -100,6 +102,7 @@ private:
};
nsWeakPtr mDocument;
nsRefPtr<txResultRecycler> mRecycler;
};
/* d0a75e02-b5e7-11d5-a7f2-df109fb8a1fc */

Просмотреть файл

@ -58,7 +58,10 @@ NS_INTERFACE_MAP_BEGIN(nsXPathExpression)
NS_INTERFACE_MAP_ENTRY_EXTERNAL_DOM_CLASSINFO(XPathExpression)
NS_INTERFACE_MAP_END
nsXPathExpression::nsXPathExpression(Expr* aExpression) : mExpression(aExpression)
nsXPathExpression::nsXPathExpression(Expr* aExpression,
txResultRecycler* aRecycler)
: mExpression(aExpression),
mRecycler(aRecycler)
{
}
@ -119,29 +122,29 @@ nsXPathExpression::Evaluate(nsIDOMNode *aContextNode,
Document document(ownerDOMDocument);
Node* node = document.createWrapper(aContextNode);
EvalContextImpl eContext(node);
ExprResult* exprResult = mExpression->evaluate(&eContext);
NS_ENSURE_TRUE(exprResult, NS_ERROR_OUT_OF_MEMORY);
EvalContextImpl eContext(node, mRecycler);
nsRefPtr<txAExprResult> exprResult;
rv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, rv);
PRUint16 resultType = aType;
if (aType == nsIDOMXPathResult::ANY_TYPE) {
short exprResultType = exprResult->getResultType();
switch (exprResultType) {
case ExprResult::NUMBER:
case txAExprResult::NUMBER:
resultType = nsIDOMXPathResult::NUMBER_TYPE;
break;
case ExprResult::STRING:
case txAExprResult::STRING:
resultType = nsIDOMXPathResult::STRING_TYPE;
break;
case ExprResult::BOOLEAN:
case txAExprResult::BOOLEAN:
resultType = nsIDOMXPathResult::BOOLEAN_TYPE;
break;
case ExprResult::NODESET:
case txAExprResult::NODESET:
resultType = nsIDOMXPathResult::UNORDERED_NODE_ITERATOR_TYPE;
break;
case ExprResult::RESULT_TREE_FRAGMENT:
case txAExprResult::RESULT_TREE_FRAGMENT:
NS_ERROR("Can't return a tree fragment!");
delete exprResult;
return NS_ERROR_FAILURE;
}
}
@ -154,7 +157,6 @@ nsXPathExpression::Evaluate(nsIDOMNode *aContextNode,
NS_ENSURE_TRUE(xpathResult, NS_ERROR_OUT_OF_MEMORY);
}
rv = xpathResult->SetExprResult(exprResult, resultType);
delete exprResult;
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(xpathResult, aResult);
@ -165,9 +167,10 @@ nsXPathExpression::Evaluate(nsIDOMNode *aContextNode,
* EvalContextImpl bases on only one context node and no variables
*/
nsresult nsXPathExpression::EvalContextImpl::getVariable(PRInt32 aNamespace,
nsIAtom* aLName,
ExprResult*& aResult)
nsresult
nsXPathExpression::EvalContextImpl::getVariable(PRInt32 aNamespace,
nsIAtom* aLName,
txAExprResult*& aResult)
{
aResult = 0;
return NS_ERROR_INVALID_ARG;
@ -184,6 +187,11 @@ void* nsXPathExpression::EvalContextImpl::getPrivateContext()
return nsnull;
}
txResultRecycler* nsXPathExpression::EvalContextImpl::recycler()
{
return mRecycler;
}
void nsXPathExpression::EvalContextImpl::receiveError(const nsAString& aMsg,
nsresult aRes)
{

Просмотреть файл

@ -42,6 +42,8 @@
#include "nsIDOMXPathExpression.h"
#include "txIXPathContext.h"
#include "txResultRecycler.h"
#include "nsAutoPtr.h"
class Expr;
@ -51,7 +53,7 @@ class Expr;
class nsXPathExpression : public nsIDOMXPathExpression
{
public:
nsXPathExpression(Expr* aExpression);
nsXPathExpression(Expr* aExpression, txResultRecycler* aRecycler);
virtual ~nsXPathExpression();
// nsISupports interface
@ -62,12 +64,13 @@ public:
private:
Expr* mExpression;
nsRefPtr<txResultRecycler> mRecycler;
class EvalContextImpl : public txIEvalContext
{
public:
EvalContextImpl(Node* aContextNode)
:mNode(aContextNode), mLastError(NS_OK)
EvalContextImpl(Node* aContextNode, txResultRecycler* aRecycler)
: mNode(aContextNode), mLastError(NS_OK), mRecycler(aRecycler)
{
}
@ -84,6 +87,7 @@ private:
private:
Node* mNode;
nsresult mLastError;
nsRefPtr<txResultRecycler> mRecycler;
};
};

Просмотреть файл

@ -264,7 +264,7 @@ nsXPathResult::ContentRemoved(nsIDocument* aDocument,
}
NS_IMETHODIMP
nsXPathResult::SetExprResult(ExprResult* aExprResult, PRUint16 aResultType)
nsXPathResult::SetExprResult(txAExprResult* aExprResult, PRUint16 aResultType)
{
Reset();
@ -287,7 +287,7 @@ nsXPathResult::SetExprResult(ExprResult* aExprResult, PRUint16 aResultType)
return NS_OK;
}
if (aExprResult->getResultType() == ExprResult::NODESET) {
if (aExprResult->getResultType() == txAExprResult::NODESET) {
nsresult rv = NS_OK;
NodeSet* nodeSet = (NodeSet*)aExprResult;

Просмотреть файл

@ -46,7 +46,7 @@
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
class ExprResult;
class txAExprResult;
// {15b9b301-2012-11d6-a7f2-e6d0a678995c}
#define NS_IXPATHRESULT_IID \
@ -56,7 +56,7 @@ class nsIXPathResult : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IXPATHRESULT_IID)
NS_IMETHOD SetExprResult(ExprResult* aExprResult,
NS_IMETHOD SetExprResult(txAExprResult* aExprResult,
PRUint16 aResultType) = 0;
};
@ -81,7 +81,7 @@ public:
NS_DECL_NSIDOCUMENTOBSERVER
// nsIXPathResult interface
NS_IMETHOD SetExprResult(ExprResult* aExprResult,
NS_IMETHOD SetExprResult(txAExprResult* aExprResult,
PRUint16 aResultType);
private:
void Invalidate();

Просмотреть файл

@ -33,6 +33,7 @@
#include "Expr.h"
#include "ExprResult.h"
#include "primitives.h"
#include "txIXPathContext.h"
/**
* Creates a new AdditiveExpr using the given operator
@ -55,26 +56,23 @@ AdditiveExpr::~AdditiveExpr() {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* AdditiveExpr::evaluate(txIEvalContext* aContext)
nsresult
AdditiveExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
double rightDbl = Double::NaN;
ExprResult* exprRes = 0;
*aResult = nsnull;
if ( rightExpr ) {
exprRes = rightExpr->evaluate(aContext);
if ( exprRes ) rightDbl = exprRes->numberValue();
delete exprRes;
}
nsRefPtr<txAExprResult> exprRes;
nsresult rv = rightExpr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
double leftDbl = Double::NaN;
if ( leftExpr ) {
exprRes = leftExpr->evaluate(aContext);
if ( exprRes ) leftDbl = exprRes->numberValue();
delete exprRes;
}
double rightDbl = exprRes->numberValue();
rv = leftExpr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
double leftDbl = exprRes->numberValue();
double result = 0;
switch ( op ) {
case SUBTRACTION:
result = leftDbl - rightDbl;
@ -83,7 +81,8 @@ ExprResult* AdditiveExpr::evaluate(txIEvalContext* aContext)
result = leftDbl + rightDbl;
break;
}
return new NumberResult(result);
return aContext->recycler()->getNumberResult(result, aResult);
} //-- evaluate
/**

Просмотреть файл

@ -29,6 +29,7 @@
#include "Expr.h"
#include "ExprResult.h"
#include "txIXPathContext.h"
/**
* Create a new AttributeValueTemplate
@ -59,17 +60,31 @@ void AttributeValueTemplate::addExpr(Expr* expr) {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* AttributeValueTemplate::evaluate(txIEvalContext* aContext)
nsresult
AttributeValueTemplate::evaluate(txIEvalContext* aContext,
txAExprResult** aResult)
{
*aResult = nsnull;
txListIterator iter(&expressions);
nsAutoString result;
nsRefPtr<StringResult> strRes;
nsresult rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
NS_ENSURE_SUCCESS(rv, rv);
while (iter.hasNext()) {
Expr* expr = (Expr*)iter.next();
ExprResult* exprResult = expr->evaluate(aContext);
exprResult->stringValue(result);
delete exprResult;
nsRefPtr<txAExprResult> exprResult;
nsresult rv = expr->evaluate(aContext, getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, rv);
exprResult->stringValue(strRes->mValue);
}
return new StringResult(result);
*aResult = strRes;
NS_ADDREF(*aResult);
return NS_OK;
} //-- evaluate
/**

Просмотреть файл

@ -36,6 +36,7 @@
#include "Expr.h"
#include "ExprResult.h"
#include "txIXPathContext.h"
/**
* Creates a new BooleanExpr using the given operator
@ -58,30 +59,36 @@ BooleanExpr::~BooleanExpr() {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* BooleanExpr::evaluate(txIEvalContext* aContext)
nsresult
BooleanExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
MBool lval = MB_FALSE;
ExprResult* exprRes = 0;
if ( leftExpr ) {
exprRes = leftExpr->evaluate(aContext);
if ( exprRes ) lval = exprRes->booleanValue();
delete exprRes;
*aResult = nsnull;
nsRefPtr<txAExprResult> exprRes;
nsresult rv = leftExpr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
PRBool lval = exprRes->booleanValue();
// check for early decision
if (op == OR && lval) {
aContext->recycler()->getBoolResult(PR_TRUE, aResult);
return NS_OK;
}
if (op == AND && !lval) {
aContext->recycler()->getBoolResult(PR_FALSE, aResult);
return NS_OK;
}
rv = rightExpr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
//-- check left expression for early decision
if (( op == OR ) && (lval)) return new BooleanResult(MB_TRUE);
else if ((op == AND) && (!lval)) return new BooleanResult(MB_FALSE);
MBool rval = MB_FALSE;
if ( rightExpr ) {
exprRes = rightExpr->evaluate(aContext);
if ( exprRes ) rval = exprRes->booleanValue();
delete exprRes;
}
//-- just use rval, since we already checked lval
return new BooleanResult(rval);
// just use rval, since we already checked lval
aContext->recycler()->getBoolResult(exprRes->booleanValue(), aResult);
return NS_OK;
} //-- evaluate
/**

Просмотреть файл

@ -49,23 +49,27 @@ BooleanFunctionCall::BooleanFunctionCall(BooleanFunctions aType)
* for evaluation
* @return the result of the evaluation
**/
ExprResult* BooleanFunctionCall::evaluate(txIEvalContext* aContext)
nsresult
BooleanFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
txListIterator iter(&params);
*aResult = nsnull;
txListIterator iter(&params);
switch (mType) {
case TX_BOOLEAN:
{
if (!requireParams(1, 1, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
return new BooleanResult(evaluateToBoolean((Expr*)iter.next(),
aContext));
aContext->recycler()->getBoolResult(
evaluateToBoolean((Expr*)iter.next(), aContext), aResult);
return NS_OK;
}
case TX_LANG:
{
if (!requireParams(1, 1, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsAutoString lang;
Node* node = aContext->getContextNode();
@ -89,35 +93,43 @@ ExprResult* BooleanFunctionCall::evaluate(txIEvalContext* aContext)
lang.CharAt(arg.Length()) == '-');
}
return new BooleanResult(result);
aContext->recycler()->getBoolResult(result, aResult);
return NS_OK;
}
case TX_NOT:
{
if (!requireParams(1, 1, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
return new BooleanResult(!evaluateToBoolean((Expr*)iter.next(),
aContext));
aContext->recycler()->getBoolResult(
!evaluateToBoolean((Expr*)iter.next(), aContext), aResult);
return NS_OK;
}
case TX_TRUE:
{
if (!requireParams(0, 0, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
return new BooleanResult(MB_TRUE);
aContext->recycler()->getBoolResult(PR_TRUE, aResult);
return NS_OK;
}
case TX_FALSE:
{
if (!requireParams(0, 0, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
return new BooleanResult(MB_FALSE);
aContext->recycler()->getBoolResult(PR_FALSE, aResult);
return NS_OK;
}
}
aContext->receiveError(NS_LITERAL_STRING("Internal error"),
NS_ERROR_UNEXPECTED);
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_UNEXPECTED;
}
nsresult BooleanFunctionCall::getNameAtom(nsIAtom** aAtom)

Просмотреть файл

@ -29,18 +29,13 @@
#include "ExprResult.h"
/**
* Default Constructor
**/
BooleanResult::BooleanResult() {
value = MB_FALSE;
} //-- BooleanResult
/**
* Creates a new BooleanResult with the value of the given MBool parameter
* @param boolean the MBool to use for initialization of this BooleanResult's value
**/
BooleanResult::BooleanResult(MBool boolean) {
BooleanResult::BooleanResult(PRBool boolean)
: txAExprResult(nsnull)
{
this->value = boolean;
} //-- BooleanResult
@ -48,13 +43,8 @@ BooleanResult::BooleanResult(MBool boolean) {
* Virtual Methods from ExprResult
*/
ExprResult* BooleanResult::clone()
{
return new BooleanResult(value);
}
short BooleanResult::getResultType() {
return ExprResult::BOOLEAN;
return txAExprResult::BOOLEAN;
} //-- getResultType
void BooleanResult::stringValue(nsAString& str) {

Просмотреть файл

@ -42,13 +42,13 @@
#include "nsIAtom.h"
#include "TxObject.h"
#include "nsAutoPtr.h"
#include "ExprResult.h"
/*
XPath class definitions.
Much of this code was ported from XSL:P.
*/
class ExprResult;
class NodeSet;
class txIParseContext;
class txIMatchContext;
@ -75,7 +75,8 @@ public:
* for evaluation
* @return the result of the evaluation
**/
virtual ExprResult* evaluate(txIEvalContext* aContext) = 0;
virtual nsresult evaluate(txIEvalContext* aContext,
txAExprResult** aResult) = 0;
/**
* Returns the String representation of this Expr.
@ -90,7 +91,7 @@ public:
}; //-- Expr
#define TX_DECL_EVALUATE \
ExprResult* evaluate(txIEvalContext* aContext)
nsresult evaluate(txIEvalContext* aContext, txAExprResult** aResult)
#define TX_DECL_EXPR \
TX_DECL_EVALUATE; \
@ -112,7 +113,6 @@ public:
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(txIEvalContext* aContext) = 0;
void toString(nsAString& aDest);
/**
@ -161,9 +161,10 @@ protected:
/*
* Evaluates the given Expression and converts its result to a NodeSet.
* If the result is not a NodeSet NULL is returned.
* If the result is not a NodeSet an error is returned.
*/
NodeSet* evaluateToNodeSet(Expr* aExpr, txIEvalContext* aContext);
nsresult evaluateToNodeSet(Expr* aExpr, txIEvalContext* aContext,
NodeSet** aResult);
/*
* Returns the name of the function as an atom.
@ -298,7 +299,7 @@ public:
**/
void add(Expr* expr);
void evaluatePredicates(NodeSet* aNodes, txIMatchContext* aContext);
nsresult evaluatePredicates(NodeSet* aNodes, txIMatchContext* aContext);
/**
* returns true if this predicate list is empty
@ -387,36 +388,17 @@ private:
}; //-- FilterExpr
class NumberExpr : public Expr {
class txLiteralExpr : public Expr {
public:
NumberExpr(double dbl);
txLiteralExpr(double aDbl);
txLiteralExpr(const nsAString& aStr);
TX_DECL_EXPR;
private:
double _value;
nsRefPtr<txAExprResult> mValue;
};
/**
* Represents a String expression
**/
class StringExpr : public Expr {
public:
StringExpr(const nsAString& value);
TX_DECL_EXPR;
private:
nsString value;
}; //-- StringExpr
/**
* Represents an AdditiveExpr, a binary expression that
* performs an additive operation between it's lvalue and rvalue:
@ -534,7 +516,8 @@ public:
TX_DECL_EXPR;
private:
PRBool compareResults(ExprResult* aLeft, ExprResult* aRight);
PRBool compareResults(txIEvalContext* aContext, txAExprResult* aLeft,
txAExprResult* aRight);
nsAutoPtr<Expr> mLeftExpr;
nsAutoPtr<Expr> mRightExpr;
@ -602,9 +585,9 @@ private:
* Selects from the descendants of the context node
* all nodes that match the Expr
*/
void evalDescendants(Expr* aStep, Node* aNode,
txIMatchContext* aContext,
NodeSet* resNodes);
nsresult evalDescendants(Expr* aStep, Node* aNode,
txIMatchContext* aContext,
NodeSet* resNodes);
}; //-- PathExpr

Просмотреть файл

@ -103,7 +103,7 @@ AttributeValueTemplate* ExprParser::createAttributeValueTemplate
}
else {
if (!buffer.IsEmpty()) {
Expr* strExpr = new StringExpr(buffer);
Expr* strExpr = new txLiteralExpr(buffer);
if (!strExpr) {
// XXX ErrorReport: out of memory
delete avt;
@ -154,7 +154,7 @@ AttributeValueTemplate* ExprParser::createAttributeValueTemplate
}
if (!buffer.IsEmpty()) {
Expr* strExpr = new StringExpr(buffer);
Expr* strExpr = new txLiteralExpr(buffer);
if (!strExpr) {
// XXX ErrorReport: out of memory
delete avt;
@ -351,11 +351,11 @@ Expr* ExprParser::createFilterExpr(ExprLexer& lexer, txIParseContext* aContext)
}
break;
case Token::LITERAL :
expr = new StringExpr(tok->value);
expr = new txLiteralExpr(tok->value);
break;
case Token::NUMBER:
{
expr = new NumberExpr(Double::toDouble(tok->value));
expr = new txLiteralExpr(Double::toDouble(tok->value));
break;
}
default:
@ -507,8 +507,8 @@ Expr* ExprParser::createFunctionCall(ExprLexer& lexer,
if (!parseParameters(0, lexer, aContext)) {
return 0;
}
return new StringExpr(tok->value +
NS_LITERAL_STRING(" not implemented."));
return new txLiteralExpr(tok->value +
NS_LITERAL_STRING(" not implemented."));
}
if (NS_FAILED(rv)) {

Просмотреть файл

@ -31,6 +31,8 @@
#include "primitives.h"
#include "TxObject.h"
#include "nsString.h"
#include "txResultRecycler.h"
#include "nsAutoPtr.h"
/*
* ExprResult
@ -41,11 +43,10 @@
* Note: for NodeSet, see NodeSet.h
*/
class ExprResult : public TxObject {
class txAExprResult : public TxObject
{
public:
//-- ResultTypes
friend class txResultRecycler;
enum ResultType {
NODESET,
BOOLEAN,
@ -54,13 +55,24 @@ public:
RESULT_TREE_FRAGMENT
};
virtual ~ExprResult() {};
txAExprResult(txResultRecycler* aRecycler) : mRecycler(aRecycler) {}
virtual ~txAExprResult() {};
/*
* Clones this ExprResult
* @return clone of this ExprResult
*/
virtual ExprResult* clone() = 0;
void AddRef()
{
++mRefCnt;
}
void Release()
{
if (--mRefCnt == 0) {
if (mRecycler) {
mRecycler->recycle(this);
}
else {
delete this;
}
}
}
/**
* Returns the type of ExprResult represented
@ -92,10 +104,12 @@ public:
**/
virtual double numberValue() = 0;
private:
nsAutoRefCnt mRefCnt;
nsRefPtr<txResultRecycler> mRecycler;
};
#define TX_DECL_EXPRRESULT \
virtual ExprResult* clone(); \
virtual short getResultType(); \
virtual void stringValue(nsAString& str); \
virtual nsAString* stringValuePointer(); \
@ -103,12 +117,10 @@ public:
virtual double numberValue(); \
class BooleanResult : public ExprResult {
class BooleanResult : public txAExprResult {
public:
BooleanResult();
BooleanResult(MBool boolean);
BooleanResult(MBool aValue);
TX_DECL_EXPRRESULT
@ -116,25 +128,22 @@ private:
MBool value;
};
class NumberResult : public ExprResult {
class NumberResult : public txAExprResult {
public:
NumberResult();
NumberResult(double dbl);
NumberResult(double aValue, txResultRecycler* aRecycler);
TX_DECL_EXPRRESULT
private:
double value;
};
class StringResult : public ExprResult {
class StringResult : public txAExprResult {
public:
StringResult();
StringResult(const nsAString& str);
StringResult(txResultRecycler* aRecycler);
StringResult(const nsAString& aValue, txResultRecycler* aRecycler);
TX_DECL_EXPRRESULT

Просмотреть файл

@ -58,29 +58,34 @@ FilterExpr::~FilterExpr() {
* @return the result of the evaluation
* @see Expr
**/
ExprResult* FilterExpr::evaluate(txIEvalContext* aContext)
nsresult
FilterExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
if (!aContext || !expr)
return new NodeSet;
*aResult = nsnull;
ExprResult* exprResult = expr->evaluate(aContext);
if (!exprResult)
return 0;
if (exprResult->getResultType() == ExprResult::NODESET) {
// Result is a nodeset, filter it.
evaluatePredicates((NodeSet*)exprResult, aContext);
}
else if(!isEmpty()) {
// We can't filter a non-nodeset
nsAutoString err(NS_LITERAL_STRING("Expecting nodeset as result of: "));
expr->toString(err);
aContext->receiveError(err, NS_ERROR_XSLT_NODESET_EXPECTED);
delete exprResult;
return new NodeSet;
}
nsRefPtr<txAExprResult> exprRes;
nsresult rv = expr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
return exprResult;
NS_ENSURE_TRUE(exprRes->getResultType() == txAExprResult::NODESET,
NS_ERROR_XSLT_NODESET_EXPECTED);
nsRefPtr<NodeSet> nodes =
NS_STATIC_CAST(NodeSet*, NS_STATIC_CAST(txAExprResult*, exprRes));
// null out exprRes so that we can test for shared-ness
exprRes = nsnull;
nsRefPtr<NodeSet> nonShared;
rv = aContext->recycler()->getNonSharedNodeSet(nodes,
getter_AddRefs(nonShared));
NS_ENSURE_SUCCESS(rv, rv);
rv = evaluatePredicates(nonShared, aContext);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = nonShared;
NS_ADDREF(*aResult);
return NS_OK;
} //-- evaluate
/**

Просмотреть файл

@ -57,7 +57,7 @@ PRUint32 txForwardContext::position()
}
nsresult txForwardContext::getVariable(PRInt32 aNamespace, nsIAtom* aLName,
ExprResult*& aResult)
txAExprResult*& aResult)
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->getVariable(aNamespace, aLName, aResult);
@ -75,6 +75,12 @@ void* txForwardContext::getPrivateContext()
return mInner->getPrivateContext();
}
txResultRecycler* txForwardContext::recycler()
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->recycler();
}
void txForwardContext::receiveError(const nsAString& aMsg, nsresult aRes)
{
NS_ASSERTION(mInner, "mInner is null!!!");

Просмотреть файл

@ -40,6 +40,7 @@
#define __TX_XPATH_CONTEXT
#include "txIXPathContext.h"
#include "nsAutoPtr.h"
class NodeSet;
@ -58,7 +59,7 @@ public:
private:
Node* mContext;
NodeSet* mContextSet;
nsRefPtr<NodeSet> mContextSet;
txIMatchContext* mInner;
};

Просмотреть файл

@ -27,6 +27,7 @@
#include "ExprResult.h"
#include "nsIAtom.h"
#include "txIXPathContext.h"
#include "NodeSet.h"
/**
* This class represents a FunctionCall as defined by the XSL Working Draft
@ -70,12 +71,12 @@ void FunctionCall::evaluateToString(Expr* aExpr, txIEvalContext* aContext,
nsAString& aDest)
{
NS_ASSERTION(aExpr, "missing expression");
ExprResult* exprResult = aExpr->evaluate(aContext);
if (!exprResult)
nsRefPtr<txAExprResult> exprResult;
nsresult rv = aExpr->evaluate(aContext, getter_AddRefs(exprResult));
if (NS_FAILED(rv))
return;
exprResult->stringValue(aDest);
delete exprResult;
}
/*
@ -84,13 +85,12 @@ void FunctionCall::evaluateToString(Expr* aExpr, txIEvalContext* aContext,
double FunctionCall::evaluateToNumber(Expr* aExpr, txIEvalContext* aContext)
{
NS_ASSERTION(aExpr, "missing expression");
ExprResult* exprResult = aExpr->evaluate(aContext);
if (!exprResult)
nsRefPtr<txAExprResult> exprResult;
nsresult rv = aExpr->evaluate(aContext, getter_AddRefs(exprResult));
if (NS_FAILED(rv))
return Double::NaN;
double result = exprResult->numberValue();
delete exprResult;
return result;
return exprResult->numberValue();
}
/*
@ -99,33 +99,39 @@ double FunctionCall::evaluateToNumber(Expr* aExpr, txIEvalContext* aContext)
MBool FunctionCall::evaluateToBoolean(Expr* aExpr, txIEvalContext* aContext)
{
NS_ASSERTION(aExpr, "missing expression");
ExprResult* exprResult = aExpr->evaluate(aContext);
if (!exprResult)
return MB_FALSE;
nsRefPtr<txAExprResult> exprResult;
nsresult rv = aExpr->evaluate(aContext, getter_AddRefs(exprResult));
if (NS_FAILED(rv))
return PR_FALSE;
MBool result = exprResult->booleanValue();
delete exprResult;
return result;
return exprResult->booleanValue();
}
/*
* Evaluates the given Expression and converts its result to a NodeSet.
* If the result is not a NodeSet NULL is returned.
*/
NodeSet* FunctionCall::evaluateToNodeSet(Expr* aExpr, txIEvalContext* aContext)
nsresult
FunctionCall::evaluateToNodeSet(Expr* aExpr, txIEvalContext* aContext,
NodeSet** aResult)
{
NS_ASSERTION(aExpr, "Missing expression to evaluate");
ExprResult* exprResult = aExpr->evaluate(aContext);
if (!exprResult)
return 0;
*aResult = nsnull;
if (exprResult->getResultType() != ExprResult::NODESET) {
nsRefPtr<txAExprResult> exprRes;
nsresult rv = aExpr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
if (exprRes->getResultType() != txAExprResult::NODESET) {
aContext->receiveError(NS_LITERAL_STRING("NodeSet expected as argument"), NS_ERROR_XSLT_NODESET_EXPECTED);
delete exprResult;
return 0;
return NS_ERROR_XSLT_NODESET_EXPECTED;
}
return (NodeSet*)exprResult;
*aResult =
NS_STATIC_CAST(NodeSet*, NS_STATIC_CAST(txAExprResult*, exprRes));
NS_ADDREF(*aResult);
return NS_OK;
}
PRBool FunctionCall::requireParams(PRInt32 aParamCountMin,

Просмотреть файл

@ -43,9 +43,10 @@
#include "nsIAtom.h"
#include "txError.h"
class ExprResult;
class txAExprResult;
class FunctionCall;
class Node;
class txResultRecycler;
/*
* txIParseContext
@ -107,7 +108,7 @@ public:
* given namespace and local name.
*/
virtual nsresult getVariable(PRInt32 aNamespace, nsIAtom* aLName,
ExprResult*& aResult) = 0;
txAExprResult*& aResult) = 0;
/*
* Is whitespace stripping allowed for the given node?
@ -120,6 +121,8 @@ public:
*/
virtual void* getPrivateContext() = 0;
virtual txResultRecycler* recycler() = 0;
/*
* Callback to be used by the expression/pattern if errors are detected.
*/
@ -128,9 +131,10 @@ public:
#define TX_DECL_MATCH_CONTEXT \
nsresult getVariable(PRInt32 aNamespace, nsIAtom* aLName, \
ExprResult*& aResult); \
txAExprResult*& aResult); \
MBool isStripSpaceAllowed(Node* aNode); \
void* getPrivateContext(); \
txResultRecycler* recycler(); \
void receiveError(const nsAString& aMsg, nsresult aRes)
class txIEvalContext : public txIMatchContext

Просмотреть файл

@ -0,0 +1,86 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* IBM Corporation. All Rights Reserved.
*
* Contributor(s):
* IBM Corporation
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "Expr.h"
txLiteralExpr::txLiteralExpr(double aDbl)
: mValue(new NumberResult(aDbl, nsnull))
{
}
txLiteralExpr::txLiteralExpr(const nsAString& aStr)
: mValue(new StringResult(aStr, nsnull))
{
}
nsresult
txLiteralExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
NS_ENSURE_TRUE(mValue, NS_ERROR_OUT_OF_MEMORY);
*aResult = mValue;
NS_ADDREF(*aResult);
return NS_OK;
}
void
txLiteralExpr::toString(nsAString& aStr)
{
switch (mValue->getResultType()) {
case txAExprResult::NUMBER:
{
Double::toString(mValue->numberValue(), aStr);
return;
}
case txAExprResult::STRING:
{
StringResult* strRes =
NS_STATIC_CAST(StringResult*, NS_STATIC_CAST(txAExprResult*,
mValue));
PRUnichar ch = '\'';
if (strRes->mValue.FindChar(ch) != kNotFound) {
ch = '\"';
}
aStr.Append(ch);
aStr.Append(strRes->mValue);
aStr.Append(ch);
return;
}
}
}

Просмотреть файл

@ -54,13 +54,15 @@ LocationStep::LocationStep(nsAutoPtr<txNodeTest> aNodeTest,
* @return the result of the evaluation
* @see Expr
**/
ExprResult* LocationStep::evaluate(txIEvalContext* aContext)
nsresult
LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
NS_ASSERTION(aContext, "internal error");
*aResult = nsnull;
NodeSet* nodes = new NodeSet();
if (!nodes)
return 0;
nsRefPtr<NodeSet> nodes;
nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
MBool reverse = MB_FALSE;
@ -188,13 +190,18 @@ ExprResult* LocationStep::evaluate(txIEvalContext* aContext)
} //-- switch
//-- apply predicates
if (!isEmpty())
evaluatePredicates(nodes, aContext);
if (!isEmpty()) {
rv = evaluatePredicates(nodes, aContext);
NS_ENSURE_SUCCESS(rv, rv);
}
if (reverse)
nodes->reverse();
return nodes;
*aResult = nodes;
NS_ADDREF(*aResult);
return NS_OK;
}
void LocationStep::fromDescendants(Node* node, txIMatchContext* cs,

Просмотреть файл

@ -39,6 +39,7 @@
#include "ExprResult.h"
#include <math.h>
#include "primitives.h"
#include "txIXPathContext.h"
/**
* Creates a new MultiplicativeExpr using the given operator
@ -61,24 +62,21 @@ MultiplicativeExpr::~MultiplicativeExpr() {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* MultiplicativeExpr::evaluate(txIEvalContext* aContext)
nsresult
MultiplicativeExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
double rightDbl = Double::NaN;
ExprResult* exprRes = 0;
*aResult = nsnull;
if ( rightExpr ) {
exprRes = rightExpr->evaluate(aContext);
if ( exprRes ) rightDbl = exprRes->numberValue();
delete exprRes;
}
nsRefPtr<txAExprResult> exprRes;
nsresult rv = rightExpr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
double leftDbl = Double::NaN;
if ( leftExpr ) {
exprRes = leftExpr->evaluate(aContext);
if ( exprRes ) leftDbl = exprRes->numberValue();
delete exprRes;
}
double rightDbl = exprRes->numberValue();
rv = leftExpr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
double leftDbl = exprRes->numberValue();
double result = 0;
switch ( op ) {
@ -118,7 +116,8 @@ ExprResult* MultiplicativeExpr::evaluate(txIEvalContext* aContext)
result = leftDbl * rightDbl;
break;
}
return new NumberResult(result);
return aContext->recycler()->getNumberResult(result, aResult);
} //-- evaluate
/**

Просмотреть файл

@ -56,7 +56,7 @@ PRUint32 txNodeSetContext::position()
}
nsresult txNodeSetContext::getVariable(PRInt32 aNamespace, nsIAtom* aLName,
ExprResult*& aResult)
txAExprResult*& aResult)
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->getVariable(aNamespace, aLName, aResult);
@ -74,6 +74,12 @@ void* txNodeSetContext::getPrivateContext()
return mInner->getPrivateContext();
}
txResultRecycler* txNodeSetContext::recycler()
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->recycler();
}
void txNodeSetContext::receiveError(const nsAString& aMsg, nsresult aRes)
{
NS_ASSERTION(mInner, "mInner is null!!!");

Просмотреть файл

@ -41,6 +41,7 @@
#include "txIXPathContext.h"
#include "NodeSet.h"
#include "nsAutoPtr.h"
class txNodeSetContext : public txIEvalContext
{
@ -67,22 +68,9 @@ public:
TX_DECL_EVAL_CONTEXT;
protected:
NodeSet* mContextSet;
nsRefPtr<NodeSet> mContextSet;
PRUint32 mPosition;
txIMatchContext* mInner;
};
class txOwningNodeSetContext : public txNodeSetContext
{
public:
txOwningNodeSetContext(NodeSet* aContextNodeSet, txIMatchContext* aContext)
: txNodeSetContext(aContextNodeSet, aContext)
{
}
virtual ~txOwningNodeSetContext()
{
delete mContextSet;
}
};
#endif // __TX_XPATH_SET_CONTEXT

Просмотреть файл

@ -57,38 +57,40 @@ NodeSetFunctionCall::NodeSetFunctionCall(NodeSetFunctions aType)
* for evaluation
* @return the result of the evaluation
*/
ExprResult* NodeSetFunctionCall::evaluate(txIEvalContext* aContext) {
nsresult
NodeSetFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
*aResult = nsnull;
nsresult rv = NS_OK;
txListIterator iter(&params);
switch (mType) {
case COUNT:
{
if (!requireParams(1, 1, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
NodeSet* nodes;
nodes = evaluateToNodeSet((Expr*)iter.next(), aContext);
if (!nodes)
return new StringResult(NS_LITERAL_STRING("error"));
nsRefPtr<NodeSet> nodes;
rv = evaluateToNodeSet((Expr*)iter.next(), aContext,
getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
double count = nodes->size();
delete nodes;
return new NumberResult(count);
return aContext->recycler()->getNumberResult(nodes->size(),
aResult);
}
case ID:
{
if (!requireParams(1, 1, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
ExprResult* exprResult;
exprResult = ((Expr*)iter.next())->evaluate(aContext);
if (!exprResult)
return new StringResult(NS_LITERAL_STRING("error"));
nsRefPtr<txAExprResult> exprResult;
rv = ((Expr*)iter.next())->evaluate(aContext,
getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, rv);
NodeSet* resultSet = new NodeSet();
if (!resultSet) {
// XXX ErrorReport: out of memory
return 0;
}
nsRefPtr<NodeSet> resultSet;
rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
NS_ENSURE_SUCCESS(rv, rv);
Document* contextDoc = 0;
Node* contextNode = aContext->getContextNode();
@ -97,8 +99,10 @@ ExprResult* NodeSetFunctionCall::evaluate(txIEvalContext* aContext) {
else
contextDoc = contextNode->getOwnerDocument();
if (exprResult->getResultType() == ExprResult::NODESET) {
NodeSet* nodes = (NodeSet*)exprResult;
if (exprResult->getResultType() == txAExprResult::NODESET) {
NodeSet* nodes = NS_STATIC_CAST(NodeSet*,
NS_STATIC_CAST(txAExprResult*,
exprResult));
int i;
for (i = 0; i < nodes->size(); i++) {
nsAutoString idList;
@ -123,38 +127,41 @@ ExprResult* NodeSetFunctionCall::evaluate(txIEvalContext* aContext) {
resultSet->add(idNode);
}
}
delete exprResult;
return resultSet;
*aResult = resultSet;
NS_ADDREF(*aResult);
return NS_OK;
}
case LAST:
{
if (!requireParams(0, 0, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
return new NumberResult(aContext->size());
return aContext->recycler()->getNumberResult(aContext->size(),
aResult);
}
case LOCAL_NAME:
case NAME:
case NAMESPACE_URI:
{
if (!requireParams(0, 1, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
Node* node = 0;
// Check for optional arg
if (iter.hasNext()) {
NodeSet* nodes;
nodes = evaluateToNodeSet((Expr*)iter.next(), aContext);
if (!nodes)
return new StringResult(NS_LITERAL_STRING("error"));
nsRefPtr<NodeSet> nodes;
rv = evaluateToNodeSet((Expr*)iter.next(), aContext,
getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
if (nodes->isEmpty()) {
delete nodes;
return new StringResult();
aContext->recycler()->getEmptyStringResult(aResult);
return NS_OK;
}
node = nodes->get(0);
delete nodes;
}
else {
node = aContext->getContextNode();
@ -163,13 +170,17 @@ ExprResult* NodeSetFunctionCall::evaluate(txIEvalContext* aContext) {
switch (mType) {
case LOCAL_NAME:
{
nsAutoString localName;
StringResult* strRes = nsnull;
rv = aContext->recycler()->getStringResult(&strRes);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = strRes;
#ifdef TX_EXE
nsCOMPtr<nsIAtom> localNameAtom;
node->getLocalName(getter_AddRefs(localNameAtom));
if (localNameAtom) {
// Node has a localName
localNameAtom->ToString(localName);
localNameAtom->ToString(strRes->mValue);
}
#else
// The mozilla HTML-elements returns different casing for
@ -179,18 +190,20 @@ ExprResult* NodeSetFunctionCall::evaluate(txIEvalContext* aContext) {
nsCOMPtr<nsIDOMNode> mozNode =
do_QueryInterface(node->getNSObj());
NS_ASSERTION(mozNode, "wrapper doesn't wrap a nsIDOMNode");
mozNode->GetLocalName(localName);
mozNode->GetLocalName(strRes->mValue);
#endif
return new StringResult(localName);
return NS_OK;
}
case NAMESPACE_URI:
{
StringResult* result = new StringResult();
if (result) {
node->getNamespaceURI(result->mValue);
}
return result;
StringResult* strRes = nsnull;
rv = aContext->recycler()->getStringResult(&strRes);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = strRes;
node->getNamespaceURI(strRes->mValue);
return NS_OK;
}
case NAME:
{
@ -198,20 +211,24 @@ ExprResult* NodeSetFunctionCall::evaluate(txIEvalContext* aContext) {
case Node::ATTRIBUTE_NODE:
case Node::ELEMENT_NODE:
case Node::PROCESSING_INSTRUCTION_NODE:
{
// XXX Namespace: namespaces have a name
StringResult* result = new StringResult();
if (result) {
node->getNodeName(result->mValue);
}
return result;
{
StringResult* strRes = nsnull;
rv = aContext->recycler()->getStringResult(&strRes);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = strRes;
node->getNodeName(strRes->mValue);
return NS_OK;
}
default:
{
break;
aContext->recycler()->getEmptyStringResult(aResult);
return NS_OK;
}
}
return new StringResult();
}
default:
{
@ -222,15 +239,16 @@ ExprResult* NodeSetFunctionCall::evaluate(txIEvalContext* aContext) {
case POSITION:
{
if (!requireParams(0, 0, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
return new NumberResult(aContext->position());
return aContext->recycler()->getNumberResult(aContext->position(),
aResult);
}
}
aContext->receiveError(NS_LITERAL_STRING("Internal error"),
NS_ERROR_UNEXPECTED);
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_UNEXPECTED;
}
nsresult NodeSetFunctionCall::getNameAtom(nsIAtom** aAtom)

Просмотреть файл

@ -55,59 +55,67 @@ NumberFunctionCall::NumberFunctionCall(NumberFunctions aType)
* for evaluation
* @return the result of the evaluation
*/
ExprResult* NumberFunctionCall::evaluate(txIEvalContext* aContext)
nsresult
NumberFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
txListIterator iter(&params);
*aResult = nsnull;
txListIterator iter(&params);
if (mType == NUMBER) {
if (!requireParams(0, 1, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
}
else {
if (!requireParams(1, 1, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
}
switch (mType) {
case CEILING:
{
double dbl = evaluateToNumber((Expr*)iter.next(), aContext);
if (Double::isNaN(dbl) || Double::isInfinite(dbl))
return new NumberResult(dbl);
if (!Double::isNaN(dbl) && !Double::isInfinite(dbl)) {
if (Double::isNeg(dbl) && dbl > -1) {
dbl *= 0;
}
else {
dbl = ceil(dbl);
}
}
if (Double::isNeg(dbl) && dbl > -1)
return new NumberResult(0 * dbl);
return new NumberResult(ceil(dbl));
return aContext->recycler()->getNumberResult(dbl, aResult);
}
case FLOOR:
{
double dbl = evaluateToNumber((Expr*)iter.next(), aContext);
if (Double::isNaN(dbl) ||
Double::isInfinite(dbl) ||
(dbl == 0 && Double::isNeg(dbl)))
return new NumberResult(dbl);
if (!Double::isNaN(dbl) &&
!Double::isInfinite(dbl) &&
!(dbl == 0 && Double::isNeg(dbl))) {
dbl = floor(dbl);
}
return new NumberResult(floor(dbl));
return aContext->recycler()->getNumberResult(dbl, aResult);
}
case ROUND:
{
double dbl = evaluateToNumber((Expr*)iter.next(), aContext);
if (Double::isNaN(dbl) || Double::isInfinite(dbl))
return new NumberResult(dbl);
if (!Double::isNaN(dbl) && !Double::isInfinite(dbl)) {
if (Double::isNeg(dbl) && dbl >= -0.5) {
dbl *= 0;
}
else {
dbl = floor(dbl + 0.5);
}
}
if (Double::isNeg(dbl) && dbl >= -0.5)
return new NumberResult(0 * dbl);
return new NumberResult(floor(dbl + 0.5));
return aContext->recycler()->getNumberResult(dbl, aResult);
}
case SUM:
{
NodeSet* nodes;
nodes = evaluateToNodeSet((Expr*)iter.next(), aContext);
if (!nodes)
return new StringResult(NS_LITERAL_STRING("error"));
nsRefPtr<NodeSet> nodes;
nsresult rv = evaluateToNodeSet((Expr*)iter.next(), aContext,
getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
double res = 0;
int i;
@ -116,26 +124,27 @@ ExprResult* NumberFunctionCall::evaluate(txIEvalContext* aContext)
XMLDOMUtils::getNodeValue(nodes->get(i), resultStr);
res += Double::toDouble(resultStr);
}
delete nodes;
return new NumberResult(res);
return aContext->recycler()->getNumberResult(res, aResult);
}
case NUMBER:
{
double res;
if (iter.hasNext()) {
return new NumberResult(
evaluateToNumber((Expr*)iter.next(), aContext));
res = evaluateToNumber((Expr*)iter.next(), aContext);
}
nsAutoString resultStr;
XMLDOMUtils::getNodeValue(aContext->getContextNode(), resultStr);
return new NumberResult(Double::toDouble(resultStr));
else {
nsAutoString resultStr;
XMLDOMUtils::getNodeValue(aContext->getContextNode(),
resultStr);
res = Double::toDouble(resultStr);
}
return aContext->recycler()->getNumberResult(res, aResult);
}
}
aContext->receiveError(NS_LITERAL_STRING("Internal error"),
NS_ERROR_UNEXPECTED);
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_UNEXPECTED;
}
nsresult NumberFunctionCall::getNameAtom(nsIAtom** aAtom)

Просмотреть файл

@ -34,29 +34,22 @@
/**
* Default Constructor
**/
NumberResult::NumberResult() {
value = 0.0;
} //-- NumberResult
/**
* Creates a new NumberResult with the value of the given double parameter
* @param dbl the double to use for initialization of this NumberResult's value
**/
NumberResult::NumberResult(double dbl) {
this->value = dbl;
NumberResult::NumberResult(double aValue, txResultRecycler* aRecycler)
: txAExprResult(aRecycler), value(aValue)
{
} //-- NumberResult
/*
* Virtual Methods from ExprResult
*/
ExprResult* NumberResult::clone()
{
return new NumberResult(value);
}
short NumberResult::getResultType() {
return ExprResult::NUMBER;
return txAExprResult::NUMBER;
} //-- getResultType
void NumberResult::stringValue(nsAString& str) {

Просмотреть файл

@ -94,77 +94,93 @@ void PathExpr::addExpr(Expr* expr, PathOperator pathOp)
* for evaluation
* @return the result of the evaluation
**/
ExprResult* PathExpr::evaluate(txIEvalContext* aContext)
nsresult
PathExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
if (!aContext || (expressions.getLength() == 0)) {
NS_ASSERTION(0, "internal error");
return new StringResult(NS_LITERAL_STRING("error"));
}
*aResult = nsnull;
NodeSet* nodes = new NodeSet(aContext->getContextNode());
if (!nodes) {
// XXX ErrorReport: out of memory
NS_ASSERTION(0, "out of memory");
return 0;
}
nsRefPtr<NodeSet> nodes;
nsresult rv = aContext->recycler()->getNodeSet(aContext->getContextNode(),
getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
txListIterator iter(&expressions);
PathExprItem* pxi;
while ((pxi = (PathExprItem*)iter.next())) {
NodeSet* tmpNodes = 0;
nsRefPtr<NodeSet> tmpNodes;
txNodeSetContext eContext(nodes, aContext);
while (eContext.hasNext()) {
eContext.next();
Node* node = eContext.getContextNode();
NodeSet* resNodes;
nsRefPtr<NodeSet> resNodes;
if (pxi->pathOp == DESCENDANT_OP) {
resNodes = new NodeSet;
evalDescendants(pxi->expr, node, &eContext, resNodes);
rv = aContext->recycler()->getNodeSet(getter_AddRefs(resNodes));
NS_ENSURE_SUCCESS(rv, rv);
rv = evalDescendants(pxi->expr, node, &eContext, resNodes);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
ExprResult *res = pxi->expr->evaluate(&eContext);
if (!res || (res->getResultType() != ExprResult::NODESET)) {
nsRefPtr<txAExprResult> res;
rv = pxi->expr->evaluate(&eContext, getter_AddRefs(res));
NS_ENSURE_SUCCESS(rv, rv);
if (res->getResultType() != txAExprResult::NODESET) {
//XXX ErrorReport: report nonnodeset error
delete res;
res = new NodeSet;
return NS_ERROR_XSLT_NODESET_EXPECTED;
}
resNodes = (NodeSet*)res;
resNodes = NS_STATIC_CAST(NodeSet*,
NS_STATIC_CAST(txAExprResult*,
res));
}
if (tmpNodes) {
tmpNodes->add(resNodes);
delete resNodes;
}
else
tmpNodes = resNodes;
if (!resNodes->isEmpty()) {
nsRefPtr<NodeSet> oldSet;
oldSet.swap(tmpNodes);
rv = aContext->recycler()->
getNonSharedNodeSet(oldSet, getter_AddRefs(tmpNodes));
NS_ENSURE_SUCCESS(rv, rv);
tmpNodes->add(resNodes);
}
}
else {
tmpNodes = resNodes;
}
}
delete nodes;
nodes = tmpNodes;
if (!nodes || (nodes->size() == 0)) break;
if (nodes->isEmpty()) {
break;
}
}
return nodes;
*aResult = nodes;
NS_ADDREF(*aResult);
return NS_OK;
} //-- evaluate
/**
* Selects from the descendants of the context node
* all nodes that match the Expr
**/
void PathExpr::evalDescendants (Expr* aStep, Node* aNode,
txIMatchContext* aContext,
NodeSet* resNodes)
nsresult
PathExpr::evalDescendants(Expr* aStep, Node* aNode, txIMatchContext* aContext,
NodeSet* resNodes)
{
txSingleNodeContext eContext(aNode, aContext);
ExprResult *res = aStep->evaluate(&eContext);
if (!res || (res->getResultType() != ExprResult::NODESET)) {
nsRefPtr<txAExprResult> res;
nsresult rv = aStep->evaluate(&eContext, getter_AddRefs(res));
NS_ENSURE_SUCCESS(rv, rv);
if (res->getResultType() != txAExprResult::NODESET) {
//XXX ErrorReport: report nonnodeset error
return NS_ERROR_XSLT_NODESET_EXPECTED;
}
else {
resNodes->add((NodeSet*)res);
}
delete res;
resNodes->add(NS_STATIC_CAST(NodeSet*, NS_STATIC_CAST(txAExprResult*,
res)));
MBool filterWS = aContext->isStripSpaceAllowed(aNode);
@ -173,10 +189,14 @@ void PathExpr::evalDescendants (Expr* aStep, Node* aNode,
if (!(filterWS &&
(child->getNodeType() == Node::TEXT_NODE ||
child->getNodeType() == Node::CDATA_SECTION_NODE) &&
XMLUtils::isWhitespace(child)))
evalDescendants(aStep, child, aContext, resNodes);
XMLUtils::isWhitespace(child))) {
rv = evalDescendants(aStep, child, aContext, resNodes);
NS_ENSURE_SUCCESS(rv, rv);
}
child = child->getNextSibling();
}
return NS_OK;
} //-- evalDescendants
/**

Просмотреть файл

@ -56,14 +56,15 @@ void PredicateList::add(Expr* expr)
predicates.add(expr);
} // add
void PredicateList::evaluatePredicates(NodeSet* nodes,
txIMatchContext* aContext)
nsresult
PredicateList::evaluatePredicates(NodeSet* nodes,
txIMatchContext* aContext)
{
NS_ASSERTION(nodes, "called evaluatePredicates with NULL NodeSet");
if (!nodes)
return;
NodeSet newNodes;
nsRefPtr<NodeSet> newNodes;
nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(newNodes));
NS_ENSURE_SUCCESS(rv, rv);
txListIterator iter(&predicates);
while (iter.hasNext() && !nodes->isEmpty()) {
Expr* expr = (Expr*)iter.next();
@ -73,30 +74,32 @@ void PredicateList::evaluatePredicates(NodeSet* nodes,
* or, if the result is a number, add the node with the right
* position
*/
newNodes.clear();
newNodes->clear();
while (predContext.hasNext()) {
predContext.next();
ExprResult* exprResult = expr->evaluate(&predContext);
if (!exprResult)
break;
nsRefPtr<txAExprResult> exprResult;
rv = expr->evaluate(&predContext, getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, rv);
switch(exprResult->getResultType()) {
case ExprResult::NUMBER :
case txAExprResult::NUMBER:
// handle default, [position() == numberValue()]
if ((double)predContext.position() ==
exprResult->numberValue())
newNodes.append(predContext.getContextNode());
newNodes->append(predContext.getContextNode());
break;
default:
if (exprResult->booleanValue())
newNodes.append(predContext.getContextNode());
newNodes->append(predContext.getContextNode());
break;
}
delete exprResult;
}
// Move new NodeSet to the current one
nodes->clear();
nodes->append(&newNodes);
nodes->append(newNodes);
}
return NS_OK;
}
/*

Просмотреть файл

@ -30,6 +30,7 @@
#include "Expr.h"
#include "NodeSet.h"
#include "XMLDOMUtils.h"
#include "txIXPathContext.h"
RelationalExpr::RelationalExpr(Expr* aLeftExpr, Expr* aRightExpr,
RelationalExprType aOp)
@ -41,26 +42,31 @@ RelationalExpr::RelationalExpr(Expr* aLeftExpr, Expr* aRightExpr,
* Compares the two ExprResults based on XPath 1.0 Recommendation (section 3.4)
*/
PRBool
RelationalExpr::compareResults(ExprResult* aLeft, ExprResult* aRight)
RelationalExpr::compareResults(txIEvalContext* aContext, txAExprResult* aLeft,
txAExprResult* aRight)
{
short ltype = aLeft->getResultType();
short rtype = aRight->getResultType();
nsresult rv = NS_OK;
// Handle case for just Left NodeSet or Both NodeSets
if (ltype == ExprResult::NODESET) {
if (rtype == ExprResult::BOOLEAN) {
if (ltype == txAExprResult::NODESET) {
if (rtype == txAExprResult::BOOLEAN) {
BooleanResult leftBool(aLeft->booleanValue());
return compareResults(&leftBool, aRight);
return compareResults(aContext, &leftBool, aRight);
}
NodeSet* nodeSet = NS_STATIC_CAST(NodeSet*, aLeft);
StringResult strResult;
nsRefPtr<StringResult> strResult;
rv = aContext->recycler()->getStringResult(getter_AddRefs(strResult));
NS_ENSURE_SUCCESS(rv, rv);
int i;
for (i = 0; i < nodeSet->size(); ++i) {
Node* node = nodeSet->get(i);
strResult.mValue.Truncate();
XMLDOMUtils::getNodeValue(node, strResult.mValue);
if (compareResults(&strResult, aRight)) {
strResult->mValue.Truncate();
XMLDOMUtils::getNodeValue(node, strResult->mValue);
if (compareResults(aContext, strResult, aRight)) {
return PR_TRUE;
}
}
@ -69,20 +75,23 @@ RelationalExpr::compareResults(ExprResult* aLeft, ExprResult* aRight)
}
// Handle case for Just Right NodeSet
if (rtype == ExprResult::NODESET) {
if (ltype == ExprResult::BOOLEAN) {
if (rtype == txAExprResult::NODESET) {
if (ltype == txAExprResult::BOOLEAN) {
BooleanResult rightBool(aRight->booleanValue());
return compareResults(aLeft, &rightBool);
return compareResults(aContext, aLeft, &rightBool);
}
NodeSet* nodeSet = NS_STATIC_CAST(NodeSet*, aRight);
StringResult strResult;
nsRefPtr<StringResult> strResult;
rv = aContext->recycler()->getStringResult(getter_AddRefs(strResult));
NS_ENSURE_SUCCESS(rv, rv);
int i;
for (i = 0; i < nodeSet->size(); ++i) {
Node* node = nodeSet->get(i);
strResult.mValue.Truncate();
XMLDOMUtils::getNodeValue(node, strResult.mValue);
if (compareResults(aLeft, &strResult)) {
strResult->mValue.Truncate();
XMLDOMUtils::getNodeValue(node, strResult->mValue);
if (compareResults(aContext, aLeft, strResult)) {
return PR_TRUE;
}
}
@ -96,12 +105,14 @@ RelationalExpr::compareResults(ExprResult* aLeft, ExprResult* aRight)
nsAString *lString, *rString;
// If either is a bool, compare as bools.
if (ltype == ExprResult::BOOLEAN || rtype == ExprResult::BOOLEAN) {
if (ltype == txAExprResult::BOOLEAN ||
rtype == txAExprResult::BOOLEAN) {
result = aLeft->booleanValue() == aRight->booleanValue();
}
// If either is a number, compare as numbers.
else if (ltype == ExprResult::NUMBER || rtype == ExprResult::NUMBER) {
else if (ltype == txAExprResult::NUMBER ||
rtype == txAExprResult::NUMBER) {
double lval = aLeft->numberValue();
double rval = aRight->numberValue();
#if defined(XP_WIN) || defined(XP_OS2)
@ -167,16 +178,22 @@ RelationalExpr::compareResults(ExprResult* aLeft, ExprResult* aRight)
return PR_FALSE;
}
ExprResult*
RelationalExpr::evaluate(txIEvalContext* aContext)
nsresult
RelationalExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
nsAutoPtr<ExprResult> lResult(mLeftExpr->evaluate(aContext));
NS_ENSURE_TRUE(lResult, nsnull);
*aResult = nsnull;
nsRefPtr<txAExprResult> lResult;
nsresult rv = mLeftExpr->evaluate(aContext, getter_AddRefs(lResult));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoPtr<ExprResult> rResult(mRightExpr->evaluate(aContext));
NS_ENSURE_TRUE(rResult, nsnull);
nsRefPtr<txAExprResult> rResult;
rv = mRightExpr->evaluate(aContext, getter_AddRefs(rResult));
NS_ENSURE_SUCCESS(rv, rv);
aContext->recycler()->
getBoolResult(compareResults(aContext, lResult, rResult), aResult);
return new BooleanResult(compareResults(lResult, rResult));
return NS_OK;
}
void

Просмотреть файл

@ -0,0 +1,288 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* IBM Corporation. All Rights Reserved.
*
* Contributor(s):
* IBM Corporation
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "txResultRecycler.h"
#include "ExprResult.h"
#include "NodeSet.h"
txResultRecycler::txResultRecycler()
: mEmptyStringResult(nsnull),
mTrueResult(nsnull),
mFalseResult(nsnull)
{
}
txResultRecycler::~txResultRecycler()
{
txStackIterator stringIter(&mStringResults);
while (stringIter.hasNext()) {
delete NS_STATIC_CAST(StringResult*, stringIter.next());
}
txStackIterator nodesetIter(&mNodeSetResults);
while (nodesetIter.hasNext()) {
delete NS_STATIC_CAST(NodeSet*, nodesetIter.next());
}
txStackIterator numberIter(&mNumberResults);
while (numberIter.hasNext()) {
delete NS_STATIC_CAST(NumberResult*, numberIter.next());
}
NS_IF_RELEASE(mEmptyStringResult);
NS_IF_RELEASE(mTrueResult);
NS_IF_RELEASE(mFalseResult);
}
nsresult
txResultRecycler::init()
{
NS_ASSERTION(!mEmptyStringResult && !mTrueResult && !mFalseResult,
"Already inited");
mEmptyStringResult = new StringResult(nsnull);
NS_ENSURE_TRUE(mEmptyStringResult, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(mEmptyStringResult);
mTrueResult = new BooleanResult(PR_TRUE);
NS_ENSURE_TRUE(mTrueResult, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(mTrueResult);
mFalseResult = new BooleanResult(PR_FALSE);
NS_ENSURE_TRUE(mFalseResult, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(mFalseResult);
return NS_OK;
}
void
txResultRecycler::recycle(txAExprResult* aResult)
{
NS_ASSERTION(aResult->mRefCnt == 0, "In-use txAExprResult recycled");
nsRefPtr<txResultRecycler> kungFuDeathGrip;
aResult->mRecycler.swap(kungFuDeathGrip);
nsresult rv = NS_OK;
switch (aResult->getResultType()) {
case txAExprResult::STRING:
{
rv = mStringResults.push(NS_STATIC_CAST(StringResult*, aResult));
if (NS_FAILED(rv)) {
delete aResult;
}
return;
}
case txAExprResult::NODESET:
{
rv = mNodeSetResults.push(NS_STATIC_CAST(NodeSet*, aResult));
if (NS_FAILED(rv)) {
delete aResult;
}
return;
}
case txAExprResult::NUMBER:
{
rv = mNumberResults.push(NS_STATIC_CAST(NumberResult*, aResult));
if (NS_FAILED(rv)) {
delete aResult;
}
return;
}
default:
{
delete aResult;
}
}
}
nsresult
txResultRecycler::getStringResult(StringResult** aResult)
{
if (mStringResults.isEmpty()) {
*aResult = new StringResult(this);
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
}
else {
*aResult = NS_STATIC_CAST(StringResult*, mStringResults.pop());
(*aResult)->mValue.Truncate();
(*aResult)->mRecycler = this;
}
NS_ADDREF(*aResult);
return NS_OK;
}
nsresult
txResultRecycler::getStringResult(const nsAString& aValue,
txAExprResult** aResult)
{
if (mStringResults.isEmpty()) {
*aResult = new StringResult(aValue, this);
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
}
else {
StringResult* strRes =
NS_STATIC_CAST(StringResult*, mStringResults.pop());
strRes->mValue = aValue;
strRes->mRecycler = this;
*aResult = strRes;
}
NS_ADDREF(*aResult);
return NS_OK;
}
void
txResultRecycler::getEmptyStringResult(txAExprResult** aResult)
{
*aResult = mEmptyStringResult;
NS_ADDREF(*aResult);
}
nsresult
txResultRecycler::getNodeSet(NodeSet** aResult)
{
if (mNodeSetResults.isEmpty()) {
*aResult = new NodeSet(this);
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
}
else {
*aResult = NS_STATIC_CAST(NodeSet*, mNodeSetResults.pop());
(*aResult)->clear();
(*aResult)->mRecycler = this;
}
NS_ADDREF(*aResult);
return NS_OK;
}
nsresult
txResultRecycler::getNodeSet(NodeSet* aNodeSet, NodeSet** aResult)
{
if (mNodeSetResults.isEmpty()) {
*aResult = new NodeSet(*aNodeSet, this);
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
}
else {
*aResult = NS_STATIC_CAST(NodeSet*, mNodeSetResults.pop());
(*aResult)->clear();
(*aResult)->append(aNodeSet);
(*aResult)->mRecycler = this;
}
NS_ADDREF(*aResult);
return NS_OK;
}
nsresult
txResultRecycler::getNodeSet(Node* aNode, txAExprResult** aResult)
{
if (mNodeSetResults.isEmpty()) {
*aResult = new NodeSet(aNode, this);
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
}
else {
NodeSet* nodes = NS_STATIC_CAST(NodeSet*, mNodeSetResults.pop());
nodes->clear();
nodes->append(aNode);
nodes->mRecycler = this;
*aResult = nodes;
}
NS_ADDREF(*aResult);
return NS_OK;
}
nsresult
txResultRecycler::getNodeSet(Node* aNode, NodeSet** aResult)
{
if (mNodeSetResults.isEmpty()) {
*aResult = new NodeSet(aNode, this);
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
}
else {
*aResult = NS_STATIC_CAST(NodeSet*, mNodeSetResults.pop());
(*aResult)->clear();
(*aResult)->append(aNode);
(*aResult)->mRecycler = this;
}
NS_ADDREF(*aResult);
return NS_OK;
}
nsresult
txResultRecycler::getNumberResult(double aValue, txAExprResult** aResult)
{
if (mNumberResults.isEmpty()) {
*aResult = new NumberResult(aValue, this);
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
}
else {
NumberResult* numRes =
NS_STATIC_CAST(NumberResult*, mNumberResults.pop());
numRes->value = aValue;
numRes->mRecycler = this;
*aResult = numRes;
}
NS_ADDREF(*aResult);
return NS_OK;
}
void
txResultRecycler::getBoolResult(PRBool aValue, txAExprResult** aResult)
{
*aResult = aValue ? mTrueResult : mFalseResult;
NS_ADDREF(*aResult);
}
nsresult
txResultRecycler::getNonSharedNodeSet(NodeSet* aNodeSet, NodeSet** aResult)
{
if (aNodeSet->mRefCnt > 1) {
return getNodeSet(aNodeSet, aResult);
}
*aResult = aNodeSet;
NS_ADDREF(*aResult);
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,111 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* IBM Corporation. All Rights Reserved.
*
* Contributor(s):
* IBM Corporation
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef txResultRecycler_h__
#define txResultRecycler_h__
#include "nsCOMPtr.h"
#include "txStack.h"
class txAExprResult;
class StringResult;
class NodeSet;
class Node;
class NumberResult;
class BooleanResult;
class txResultRecycler
{
public:
txResultRecycler();
~txResultRecycler();
nsresult init();
void AddRef()
{
++mRefCnt;
}
void Release()
{
if (--mRefCnt == 0) {
mRefCnt = 1; //stabilize
delete this;
}
}
/**
* Returns an txAExprResult to this recycler for reuse.
* @param aResult result to recycle
*/
void recycle(txAExprResult* aResult);
/**
* Functions to return results that will be fully used by the caller.
* Returns nsnull on out-of-memory and an inited result otherwise.
*/
nsresult getStringResult(StringResult** aResult);
nsresult getStringResult(const nsAString& aValue, txAExprResult** aResult);
nsresult getNodeSet(NodeSet** aResult);
nsresult getNodeSet(NodeSet* aNodeSet, NodeSet** aResult);
nsresult getNodeSet(Node* aNode, txAExprResult** aResult);
nsresult getNodeSet(Node* aNode, NodeSet** aResult);
nsresult getNumberResult(double aValue, txAExprResult** aResult);
/**
* Functions to return a txAExprResult that is shared across several
* clients and must not be modified. Never returns nsnull.
*/
void getEmptyStringResult(txAExprResult** aResult);
void getBoolResult(PRBool aValue, txAExprResult** aResult);
/**
* Functions that return non-shared resultsobjects
*/
nsresult getNonSharedNodeSet(NodeSet* aNodeSet, NodeSet** aResult);
private:
nsAutoRefCnt mRefCnt;
txStack mStringResults;
txStack mNodeSetResults;
txStack mNumberResults;
StringResult* mEmptyStringResult;
BooleanResult* mTrueResult;
BooleanResult* mFalseResult;
};
#endif //txResultRecycler_h__

Просмотреть файл

@ -42,17 +42,15 @@ RootExpr::RootExpr(MBool aSerialize) {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* RootExpr::evaluate(txIEvalContext* aContext)
nsresult
RootExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
Node* context;
if (!aContext || !(context = aContext->getContextNode())) {
NS_ASSERTION(0, "internal error");
return 0;
Node* context = aContext->getContextNode();
if (context->getNodeType() != Node::DOCUMENT_NODE) {
context = context->getOwnerDocument();
}
if (context->getNodeType() != Node::DOCUMENT_NODE)
return new NodeSet(context->getOwnerDocument());
return new NodeSet(context);
return aContext->recycler()->getNodeSet(context, aResult);
} //-- evaluate
/**

Просмотреть файл

@ -54,7 +54,7 @@ public:
{}
nsresult getVariable(PRInt32 aNamespace, nsIAtom* aLName,
ExprResult*& aResult)
txAExprResult*& aResult)
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->getVariable(aNamespace, aLName, aResult);
@ -72,6 +72,12 @@ public:
return mInner->getPrivateContext();
}
txResultRecycler* recycler()
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->recycler();
}
void receiveError(const nsAString& aMsg, nsresult aRes)
{
NS_ASSERTION(mInner, "mInner is null!!!");

Просмотреть файл

@ -36,6 +36,7 @@
#include "XMLDOMUtils.h"
#include "XMLUtils.h"
#include <math.h>
#include "nsReadableUtils.h"
/**
* Creates a StringFunctionCall of the given type
@ -51,39 +52,54 @@ StringFunctionCall::StringFunctionCall(StringFunctions aType) : mType(aType)
* for evaluation
* @return the result of the evaluation
**/
ExprResult* StringFunctionCall::evaluate(txIEvalContext* aContext)
nsresult
StringFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
*aResult = nsnull;
nsresult rv = NS_OK;
txListIterator iter(&params);
switch (mType) {
case CONCAT:
{
if (!requireParams(2, -1, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsAutoString resultStr;
nsRefPtr<StringResult> strRes;
rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
NS_ENSURE_SUCCESS(rv, rv);
while (iter.hasNext()) {
evaluateToString((Expr*)iter.next(), aContext, resultStr);
evaluateToString((Expr*)iter.next(), aContext, strRes->mValue);
}
return new StringResult(resultStr);
*aResult = strRes;
NS_ADDREF(*aResult);
return NS_OK;
}
case CONTAINS:
{
if (!requireParams(2, 2, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsAutoString arg1, arg2;
Expr* arg1Expr = (Expr*)iter.next();
evaluateToString((Expr*)iter.next(), aContext, arg2);
if (arg2.IsEmpty())
return new BooleanResult(PR_TRUE);
if (arg2.IsEmpty()) {
aContext->recycler()->getBoolResult(PR_TRUE, aResult);
}
else {
evaluateToString(arg1Expr, aContext, arg1);
aContext->recycler()->getBoolResult(arg1.Find(arg2) >= 0,
aResult);
}
evaluateToString(arg1Expr, aContext, arg1);
return new BooleanResult(arg1.Find(arg2) >= 0);
return NS_OK;
}
case NORMALIZE_SPACE:
{
if (!requireParams(0, 1, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsAutoString resultStr;
if (iter.hasNext())
@ -92,10 +108,13 @@ ExprResult* StringFunctionCall::evaluate(txIEvalContext* aContext)
XMLDOMUtils::getNodeValue(aContext->getContextNode(),
resultStr);
nsRefPtr<StringResult> strRes;
rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
NS_ENSURE_SUCCESS(rv, rv);
MBool addSpace = MB_FALSE;
MBool first = MB_TRUE;
nsAutoString normed;
normed.SetCapacity(resultStr.Length());
strRes->mValue.SetCapacity(resultStr.Length());
PRUnichar c;
PRUint32 src;
for (src = 0; src < resultStr.Length(); src++) {
@ -105,33 +124,41 @@ ExprResult* StringFunctionCall::evaluate(txIEvalContext* aContext)
}
else {
if (addSpace && !first)
normed.Append(PRUnichar(' '));
strRes->mValue.Append(PRUnichar(' '));
normed.Append(c);
strRes->mValue.Append(c);
addSpace = MB_FALSE;
first = MB_FALSE;
}
}
return new StringResult(normed);
*aResult = strRes;
NS_ADDREF(*aResult);
return NS_OK;
}
case STARTS_WITH:
{
if (!requireParams(2, 2, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsAutoString arg1, arg2;
Expr* arg1Expr = (Expr*)iter.next();
evaluateToString((Expr*)iter.next(), aContext, arg2);
if (arg2.IsEmpty())
return new BooleanResult(PR_TRUE);
if (arg2.IsEmpty()) {
aContext->recycler()->getBoolResult(PR_TRUE, aResult);
}
else {
evaluateToString(arg1Expr, aContext, arg1);
aContext->recycler()->getBoolResult(
StringBeginsWith(arg1, arg2), aResult);
}
evaluateToString(arg1Expr, aContext, arg1);
return new BooleanResult(arg1.Find(arg2) == 0);
return NS_OK;
}
case STRING_LENGTH:
{
if (!requireParams(0, 1, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsAutoString resultStr;
if (iter.hasNext())
@ -139,12 +166,16 @@ ExprResult* StringFunctionCall::evaluate(txIEvalContext* aContext)
else
XMLDOMUtils::getNodeValue(aContext->getContextNode(),
resultStr);
return new NumberResult(resultStr.Length());
rv = aContext->recycler()->getNumberResult(resultStr.Length(),
aResult);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
case SUBSTRING:
{
if (!requireParams(2, 3, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsAutoString src;
double start, end;
@ -154,15 +185,21 @@ ExprResult* StringFunctionCall::evaluate(txIEvalContext* aContext)
// check for NaN or +/-Inf
if (Double::isNaN(start) ||
Double::isInfinite(start) ||
start >= src.Length() + 0.5)
return new StringResult();
start >= src.Length() + 0.5) {
aContext->recycler()->getEmptyStringResult(aResult);
return NS_OK;
}
start = floor(start + 0.5) - 1;
if (iter.hasNext()) {
end = start + evaluateToNumber((Expr*)iter.next(),
aContext);
if (Double::isNaN(end) || end < 0)
return new StringResult();
if (Double::isNaN(end) || end < 0) {
aContext->recycler()->getEmptyStringResult(aResult);
return NS_OK;
}
if (end > src.Length())
end = src.Length();
@ -176,61 +213,79 @@ ExprResult* StringFunctionCall::evaluate(txIEvalContext* aContext)
if (start < 0)
start = 0;
if (start > end)
return new StringResult();
return new StringResult(Substring(src, (PRUint32)start,
(PRUint32)end - (PRUint32)start));
if (start > end) {
aContext->recycler()->getEmptyStringResult(aResult);
return NS_OK;
}
return aContext->recycler()->getStringResult(
Substring(src, (PRUint32)start, (PRUint32)(end - start)),
aResult);
}
case SUBSTRING_AFTER:
{
if (!requireParams(2, 2, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsAutoString arg1, arg2;
evaluateToString((Expr*)iter.next(), aContext, arg1);
evaluateToString((Expr*)iter.next(), aContext, arg2);
if (arg2.IsEmpty())
return new StringResult(arg1);
if (arg2.IsEmpty()) {
return aContext->recycler()->getStringResult(arg1, aResult);
}
PRInt32 idx = arg1.Find(arg2);
if (idx != kNotFound) {
PRUint32 len = arg2.Length();
return new StringResult(Substring(arg1, idx + len,
arg1.Length() - (idx + len)));
if (idx == kNotFound) {
aContext->recycler()->getEmptyStringResult(aResult);
return NS_OK;
}
return new StringResult();
PRUint32 len = arg2.Length();
return aContext->recycler()->getStringResult(
Substring(arg1, idx + len, arg1.Length() - (idx + len)),
aResult);
}
case SUBSTRING_BEFORE:
{
if (!requireParams(2, 2, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsAutoString arg1, arg2;
Expr* arg1Expr = (Expr*)iter.next();
evaluateToString((Expr*)iter.next(), aContext, arg2);
if (arg2.IsEmpty())
return new StringResult();
if (arg2.IsEmpty()) {
aContext->recycler()->getEmptyStringResult(aResult);
return NS_OK;
}
evaluateToString(arg1Expr, aContext, arg1);
PRInt32 idx = arg1.Find(arg2);
if (idx != kNotFound) {
return new StringResult(Substring(arg1, 0, idx));
if (idx == kNotFound) {
aContext->recycler()->getEmptyStringResult(aResult);
return NS_OK;
}
return new StringResult();
return aContext->recycler()->
getStringResult(Substring(arg1, 0, idx), aResult);
}
case TRANSLATE:
{
if (!requireParams(3, 3, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsRefPtr<StringResult> strRes;
rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString src;
evaluateToString((Expr*)iter.next(), aContext, src);
if (src.IsEmpty())
return new StringResult();
nsAutoString oldChars, newChars, dest;
strRes->mValue.SetCapacity(src.Length());
nsAutoString oldChars, newChars;
evaluateToString((Expr*)iter.next(), aContext, oldChars);
evaluateToString((Expr*)iter.next(), aContext, newChars);
PRUint32 i;
@ -239,32 +294,41 @@ ExprResult* StringFunctionCall::evaluate(txIEvalContext* aContext)
PRInt32 idx = oldChars.FindChar(src.CharAt(i));
if (idx != kNotFound) {
if (idx < newCharsLength)
dest.Append(newChars.CharAt((PRUint32)idx));
strRes->mValue.Append(newChars.CharAt((PRUint32)idx));
}
else {
dest.Append(src.CharAt(i));
strRes->mValue.Append(src.CharAt(i));
}
}
return new StringResult(dest);
*aResult = strRes;
NS_ADDREF(*aResult);
return NS_OK;
}
case STRING:
{
if (!requireParams(0, 1, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
nsRefPtr<StringResult> strRes;
rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString resultStr;
if (iter.hasNext())
evaluateToString((Expr*)iter.next(), aContext, resultStr);
evaluateToString((Expr*)iter.next(), aContext, strRes->mValue);
else
XMLDOMUtils::getNodeValue(aContext->getContextNode(),
resultStr);
return new StringResult(resultStr);
strRes->mValue);
*aResult = strRes;
NS_ADDREF(*aResult);
return NS_OK;
}
}
aContext->receiveError(NS_LITERAL_STRING("Internal error"),
NS_ERROR_UNEXPECTED);
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_UNEXPECTED;
}
nsresult StringFunctionCall::getNameAtom(nsIAtom** aAtom)

Просмотреть файл

@ -33,14 +33,17 @@
/**
* Default Constructor
**/
StringResult::StringResult() {
} //-- StringResult
StringResult::StringResult(txResultRecycler* aRecycler)
: txAExprResult(aRecycler)
{
}
/**
* Creates a new StringResult with the value of the given String parameter
* @param str the String to use for initialization of this StringResult's value
**/
StringResult::StringResult(const nsAString& str) : mValue(str)
StringResult::StringResult(const nsAString& aValue, txResultRecycler* aRecycler)
: txAExprResult(aRecycler), mValue(aValue)
{
}
@ -48,13 +51,8 @@ StringResult::StringResult(const nsAString& str) : mValue(str)
* Virtual Methods from ExprResult
*/
ExprResult* StringResult::clone()
{
return new StringResult(mValue);
}
short StringResult::getResultType() {
return ExprResult::STRING;
return txAExprResult::STRING;
} //-- getResultType
void StringResult::stringValue(nsAString& str) {

Просмотреть файл

@ -25,6 +25,7 @@
#include "Expr.h"
#include "ExprResult.h"
#include "txIXPathContext.h"
UnaryExpr::UnaryExpr(Expr* expr)
{
@ -43,20 +44,25 @@ UnaryExpr::~UnaryExpr()
* for evaluation.
* @return the result of the evaluation.
*/
ExprResult* UnaryExpr::evaluate(txIEvalContext* aContext)
nsresult
UnaryExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
ExprResult* exprRes = expr->evaluate(aContext);
*aResult = nsnull;
nsRefPtr<txAExprResult> exprRes;
nsresult rv = expr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
double value = exprRes->numberValue();
delete exprRes;
#ifdef HPUX
/*
* Negation of a zero doesn't produce a negative
* zero on HPUX. Perform the operation by multiplying with
* -1.
*/
return new NumberResult(-1 * value);
return aContext->recycler()->getNumberResult(-1 * value, aResult);
#else
return new NumberResult(-value);
return aContext->recycler()->getNumberResult(-value, aResult);
#endif
}

Просмотреть файл

@ -25,6 +25,7 @@
#include "Expr.h"
#include "NodeSet.h"
#include "txIXPathContext.h"
//-------------/
//- UnionExpr -/
@ -68,29 +69,34 @@ void UnionExpr::addExpr(Expr* expr) {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* UnionExpr::evaluate(txIEvalContext* aContext)
nsresult
UnionExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
NodeSet* nodes = new NodeSet();
if (!aContext || (expressions.getLength() == 0) || !nodes)
return nodes;
*aResult = nsnull;
nsRefPtr<NodeSet> nodes;
nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
txListIterator iter(&expressions);
while (iter.hasNext()) {
Expr* expr = (Expr*)iter.next();
ExprResult* exprResult = expr->evaluate(aContext);
if (!exprResult ||
exprResult->getResultType() != ExprResult::NODESET) {
delete exprResult;
delete nodes;
return new StringResult(NS_LITERAL_STRING("error"));
nsRefPtr<txAExprResult> exprResult;
rv = expr->evaluate(aContext, getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, rv);
if (exprResult->getResultType() != txAExprResult::NODESET) {
//XXX ErrorReport: report nonnodeset error
return NS_ERROR_XSLT_NODESET_EXPECTED;
}
nodes->add((NodeSet*)exprResult);
delete exprResult;
rv = nodes->add(NS_STATIC_CAST(NodeSet*, NS_STATIC_CAST(txAExprResult*,
exprResult)));
NS_ENSURE_SUCCESS(rv, rv);
}
return nodes;
*aResult = nodes;
NS_ADDREF(*aResult);
return NS_OK;
} //-- evaluate
/**

Просмотреть файл

@ -58,15 +58,15 @@ VariableRefExpr::~VariableRefExpr()
* for evaluation
* @return the result of the evaluation
**/
ExprResult* VariableRefExpr::evaluate(txIEvalContext* aContext)
nsresult
VariableRefExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
ExprResult* exprResult = 0;
nsresult rv = aContext->getVariable(mNamespace, mLocalName, exprResult);
nsresult rv = aContext->getVariable(mNamespace, mLocalName, *aResult);
if (NS_FAILED(rv)) {
// XXX report error, undefined variable
return new StringResult(NS_LITERAL_STRING("error"));
return rv;
}
return exprResult->clone();
return NS_OK;
}
/**

Просмотреть файл

@ -53,20 +53,6 @@ class txResultBuffer
public:
~txResultBuffer();
nsrefcnt AddRef()
{
return ++mRefCnt;
}
nsrefcnt Release()
{
if (--mRefCnt == 0) {
mRefCnt = 1; //stabilize
delete this;
return 0;
}
return mRefCnt;
}
nsresult addTransaction(txOutputTransaction* aTransaction);
nsresult flushToHandler(txAXMLEventHandler* aHandler);
txOutputTransaction* getLastTransaction();
@ -75,7 +61,6 @@ public:
private:
nsVoidArray mTransactions;
nsAutoRefCnt mRefCnt;
};
class txBufferingHandler : public txAXMLEventHandler
@ -87,7 +72,7 @@ public:
TX_DECL_TXAXMLEVENTHANDLER
protected:
nsRefPtr<txResultBuffer> mBuffer;
nsAutoPtr<txResultBuffer> mBuffer;
PRPackedBool mCanAddAttribute;
};

Просмотреть файл

@ -19,18 +19,23 @@ CurrentFunctionCall::CurrentFunctionCall()
* @return NodeSet containing the context node used for the complete
* Expr or Pattern.
*/
ExprResult* CurrentFunctionCall::evaluate(txIEvalContext* aContext)
nsresult
CurrentFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
*aResult = nsnull;
if (!requireParams(0, 0, aContext))
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
txExecutionState* es =
NS_STATIC_CAST(txExecutionState*, aContext->getPrivateContext());
if (!es) {
NS_ASSERTION(0,
"called xslt extension function \"current\" with wrong context");
// Just return an empty nodeset, this at least has the right
// result type.
return new NodeSet();
return NS_ERROR_UNEXPECTED;
}
return new NodeSet(es->getEvalContext()->getContextNode());
return aContext->recycler()->getNodeSet(
es->getEvalContext()->getContextNode(), aResult);
}
nsresult CurrentFunctionCall::getNameAtom(nsIAtom** aAtom)

Просмотреть файл

@ -57,81 +57,86 @@ DocumentFunctionCall::DocumentFunctionCall(const nsAString& aBaseURI)
* @param context the context node for evaluation of this Expr
* @return the result of the evaluation
*/
ExprResult* DocumentFunctionCall::evaluate(txIEvalContext* aContext)
nsresult
DocumentFunctionCall::evaluate(txIEvalContext* aContext,
txAExprResult** aResult)
{
*aResult = nsnull;
txExecutionState* es =
NS_STATIC_CAST(txExecutionState*, aContext->getPrivateContext());
NodeSet* nodeSet = new NodeSet();
NS_ENSURE_TRUE(nodeSet, nsnull);
nsRefPtr<NodeSet> nodeSet;
nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodeSet));
NS_ENSURE_SUCCESS(rv, rv);
// document(object, node-set?)
if (requireParams(1, 2, aContext)) {
txListIterator iter(&params);
Expr* param1 = (Expr*)iter.next();
ExprResult* exprResult1 = param1->evaluate(aContext);
nsAutoString baseURI;
MBool baseURISet = MB_FALSE;
if (!requireParams(1, 2, aContext)) {
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
}
if (iter.hasNext()) {
// We have 2 arguments, get baseURI from the first node
// in the resulting nodeset
Expr* param2 = (Expr*)iter.next();
ExprResult* exprResult2 = param2->evaluate(aContext);
if (exprResult2->getResultType() != ExprResult::NODESET) {
nsAutoString err(NS_LITERAL_STRING("node-set expected as second argument to document(): "));
toString(err);
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
delete exprResult1;
delete exprResult2;
return nodeSet;
}
txListIterator iter(&params);
Expr* param1 = (Expr*)iter.next();
nsRefPtr<txAExprResult> exprResult1;
rv = param1->evaluate(aContext, getter_AddRefs(exprResult1));
NS_ENSURE_SUCCESS(rv, rv);
// Make this true, even if nodeSet2 is empty. For relative URLs,
// we'll fail to load the document with an empty base URI, and for
// absolute URLs, the base URI doesn't matter
baseURISet = MB_TRUE;
nsAutoString baseURI;
MBool baseURISet = MB_FALSE;
NodeSet* nodeSet2 = (NodeSet*) exprResult2;
if (!nodeSet2->isEmpty()) {
nodeSet2->get(0)->getBaseURI(baseURI);
}
delete exprResult2;
if (iter.hasNext()) {
// We have 2 arguments, get baseURI from the first node
// in the resulting nodeset
nsRefPtr<NodeSet> nodeSet2;
rv = evaluateToNodeSet(NS_STATIC_CAST(Expr*, iter.next()),
aContext, getter_AddRefs(nodeSet2));
NS_ENSURE_SUCCESS(rv, rv);
// Make this true, even if nodeSet2 is empty. For relative URLs,
// we'll fail to load the document with an empty base URI, and for
// absolute URLs, the base URI doesn't matter
baseURISet = MB_TRUE;
if (!nodeSet2->isEmpty()) {
nodeSet2->get(0)->getBaseURI(baseURI);
}
}
if (exprResult1->getResultType() == ExprResult::NODESET) {
// The first argument is a NodeSet, iterate on its nodes
NodeSet* nodeSet1 = (NodeSet*) exprResult1;
int i;
for (i = 0; i < nodeSet1->size(); i++) {
Node* node = nodeSet1->get(i);
nsAutoString uriStr;
XMLDOMUtils::getNodeValue(node, uriStr);
if (!baseURISet) {
// if the second argument wasn't specified, use
// the baseUri of node itself
node->getBaseURI(baseURI);
}
Node* loadNode = es->retrieveDocument(uriStr, baseURI);
if (loadNode) {
nodeSet->add(loadNode);
}
}
}
else {
// The first argument is not a NodeSet
if (exprResult1->getResultType() == txAExprResult::NODESET) {
// The first argument is a NodeSet, iterate on its nodes
NodeSet* nodeSet1 = NS_STATIC_CAST(NodeSet*,
NS_STATIC_CAST(txAExprResult*,
exprResult1));
int i;
for (i = 0; i < nodeSet1->size(); i++) {
Node* node = nodeSet1->get(i);
nsAutoString uriStr;
exprResult1->stringValue(uriStr);
nsAString* base = baseURISet ? &baseURI : &mBaseURI;
Node* loadNode = es->retrieveDocument(uriStr, *base);
XMLDOMUtils::getNodeValue(node, uriStr);
if (!baseURISet) {
// if the second argument wasn't specified, use
// the baseUri of node itself
node->getBaseURI(baseURI);
}
Node* loadNode = es->retrieveDocument(uriStr, baseURI);
if (loadNode) {
nodeSet->add(loadNode);
}
}
delete exprResult1;
}
else {
// The first argument is not a NodeSet
nsAutoString uriStr;
exprResult1->stringValue(uriStr);
nsAString* base = baseURISet ? &baseURI : &mBaseURI;
Node* loadNode = es->retrieveDocument(uriStr, *base);
if (loadNode) {
nodeSet->add(loadNode);
}
}
return nodeSet;
*aResult = nodeSet;
NS_ADDREF(*aResult);
return NS_OK;
}
nsresult DocumentFunctionCall::getNameAtom(nsIAtom** aAtom)

Просмотреть файл

@ -66,73 +66,70 @@ ElementAvailableFunctionCall::ElementAvailableFunctionCall(txNamespaceMap* aMapp
* @return the result of the evaluation
* @see FunctionCall.h
**/
ExprResult* ElementAvailableFunctionCall::evaluate(txIEvalContext* aContext)
nsresult
ElementAvailableFunctionCall::evaluate(txIEvalContext* aContext,
txAExprResult** aResult)
{
ExprResult* result = nsnull;
if (requireParams(1, 1, aContext)) {
txListIterator iter(&params);
Expr* param = (Expr*) iter.next();
ExprResult* exprResult = param->evaluate(aContext);
if (exprResult &&
exprResult->getResultType() == ExprResult::STRING) {
nsAutoString property;
exprResult->stringValue(property);
txExpandedName qname;
nsresult rv = qname.init(property, mMappings, MB_TRUE);
if (NS_SUCCEEDED(rv) &&
qname.mNamespaceID == kNameSpaceID_XSLT &&
(qname.mLocalName == txXSLTAtoms::applyImports ||
qname.mLocalName == txXSLTAtoms::applyTemplates ||
qname.mLocalName == txXSLTAtoms::attribute ||
qname.mLocalName == txXSLTAtoms::attributeSet ||
qname.mLocalName == txXSLTAtoms::callTemplate ||
qname.mLocalName == txXSLTAtoms::choose ||
qname.mLocalName == txXSLTAtoms::comment ||
qname.mLocalName == txXSLTAtoms::copy ||
qname.mLocalName == txXSLTAtoms::copyOf ||
qname.mLocalName == txXSLTAtoms::decimalFormat ||
qname.mLocalName == txXSLTAtoms::element ||
// qname.mLocalName == txXSLTAtoms::fallback ||
qname.mLocalName == txXSLTAtoms::forEach ||
qname.mLocalName == txXSLTAtoms::_if ||
qname.mLocalName == txXSLTAtoms::import ||
qname.mLocalName == txXSLTAtoms::include ||
qname.mLocalName == txXSLTAtoms::key ||
qname.mLocalName == txXSLTAtoms::message ||
// qname.mLocalName == txXSLTAtoms::namespaceAlias ||
qname.mLocalName == txXSLTAtoms::number ||
qname.mLocalName == txXSLTAtoms::otherwise ||
qname.mLocalName == txXSLTAtoms::output ||
qname.mLocalName == txXSLTAtoms::param ||
qname.mLocalName == txXSLTAtoms::preserveSpace ||
qname.mLocalName == txXSLTAtoms::processingInstruction ||
qname.mLocalName == txXSLTAtoms::sort ||
qname.mLocalName == txXSLTAtoms::stripSpace ||
qname.mLocalName == txXSLTAtoms::stylesheet ||
qname.mLocalName == txXSLTAtoms::_template ||
qname.mLocalName == txXSLTAtoms::text ||
qname.mLocalName == txXSLTAtoms::transform ||
qname.mLocalName == txXSLTAtoms::valueOf ||
qname.mLocalName == txXSLTAtoms::variable ||
qname.mLocalName == txXSLTAtoms::when ||
qname.mLocalName == txXSLTAtoms::withParam)) {
result = new BooleanResult(MB_TRUE);
}
}
else {
NS_NAMED_LITERAL_STRING(err, "Invalid argument passed to element-available(), expecting String");
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
result = new StringResult(err);
}
delete exprResult;
*aResult = nsnull;
if (!requireParams(1, 1, aContext)) {
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
}
if (!result) {
result = new BooleanResult(MB_FALSE);
}
return result;
txListIterator iter(&params);
Expr* param = (Expr*) iter.next();
nsRefPtr<txAExprResult> exprResult;
nsresult rv = param->evaluate(aContext, getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString property;
exprResult->stringValue(property);
txExpandedName qname;
rv = qname.init(property, mMappings, MB_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
PRBool val = qname.mNamespaceID == kNameSpaceID_XSLT &&
(qname.mLocalName == txXSLTAtoms::applyImports ||
qname.mLocalName == txXSLTAtoms::applyTemplates ||
qname.mLocalName == txXSLTAtoms::attribute ||
qname.mLocalName == txXSLTAtoms::attributeSet ||
qname.mLocalName == txXSLTAtoms::callTemplate ||
qname.mLocalName == txXSLTAtoms::choose ||
qname.mLocalName == txXSLTAtoms::comment ||
qname.mLocalName == txXSLTAtoms::copy ||
qname.mLocalName == txXSLTAtoms::copyOf ||
qname.mLocalName == txXSLTAtoms::decimalFormat ||
qname.mLocalName == txXSLTAtoms::element ||
//qname.mLocalName == txXSLTAtoms::fallback ||
qname.mLocalName == txXSLTAtoms::forEach ||
qname.mLocalName == txXSLTAtoms::_if ||
qname.mLocalName == txXSLTAtoms::import ||
qname.mLocalName == txXSLTAtoms::include ||
qname.mLocalName == txXSLTAtoms::key ||
qname.mLocalName == txXSLTAtoms::message ||
//qname.mLocalName == txXSLTAtoms::namespaceAlias ||
qname.mLocalName == txXSLTAtoms::number ||
qname.mLocalName == txXSLTAtoms::otherwise ||
qname.mLocalName == txXSLTAtoms::output ||
qname.mLocalName == txXSLTAtoms::param ||
qname.mLocalName == txXSLTAtoms::preserveSpace ||
qname.mLocalName == txXSLTAtoms::processingInstruction ||
qname.mLocalName == txXSLTAtoms::sort ||
qname.mLocalName == txXSLTAtoms::stripSpace ||
qname.mLocalName == txXSLTAtoms::stylesheet ||
qname.mLocalName == txXSLTAtoms::_template ||
qname.mLocalName == txXSLTAtoms::text ||
qname.mLocalName == txXSLTAtoms::transform ||
qname.mLocalName == txXSLTAtoms::valueOf ||
qname.mLocalName == txXSLTAtoms::variable ||
qname.mLocalName == txXSLTAtoms::when ||
qname.mLocalName == txXSLTAtoms::withParam);
aContext->recycler()->getBoolResult(val, aResult);
return NS_OK;
}
nsresult ElementAvailableFunctionCall::getNameAtom(nsIAtom** aAtom)

Просмотреть файл

@ -103,8 +103,7 @@ Document* txLoadedDocumentsHash::Get(const nsAString& aURI)
}
txExecutionState::txExecutionState(txStylesheet* aStylesheet)
: mTemplateParams(nsnull),
mStylesheet(aStylesheet),
: mStylesheet(aStylesheet),
mNextInstruction(nsnull),
mLocalVariables(nsnull),
mRecursionDepth(0),
@ -125,7 +124,6 @@ txExecutionState::~txExecutionState()
delete mLocalVariables;
delete mEvalContext;
delete mRTFDocument;
delete mTemplateParams;
PRInt32 i;
for (i = 0; i < mTemplateRuleCount; ++i) {
@ -205,9 +203,15 @@ txExecutionState::init(Node* aNode,
rv = mKeyHash.init();
NS_ENSURE_SUCCESS(rv, rv);
mRecycler = new txResultRecycler;
NS_ENSURE_TRUE(mRecycler, NS_ERROR_OUT_OF_MEMORY);
rv = mRecycler->init();
NS_ENSURE_SUCCESS(rv, rv);
// The actual value here doesn't really matter since noone should use this
// value. But lets put something errorlike in just in case
mGlobalVarPlaceholderValue = new StringResult(NS_LITERAL_STRING("Error"));
mGlobalVarPlaceholderValue = new StringResult(NS_LITERAL_STRING("Error"), nsnull);
NS_ENSURE_TRUE(mGlobalVarPlaceholderValue, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
@ -226,25 +230,25 @@ txExecutionState::end()
nsresult
txExecutionState::getVariable(PRInt32 aNamespace, nsIAtom* aLName,
ExprResult*& aResult)
txAExprResult*& aResult)
{
nsresult rv = NS_OK;
txExpandedName name(aNamespace, aLName);
// look for a local variable
if (mLocalVariables) {
aResult = mLocalVariables->getVariable(name);
mLocalVariables->getVariable(name, &aResult);
if (aResult) {
return NS_OK;
}
}
// look for an evaluated global variable
aResult = mGlobalVariableValues.getVariable(name);
mGlobalVariableValues.getVariable(name, &aResult);
if (aResult) {
if (aResult == mGlobalVarPlaceholderValue) {
// XXX ErrorReport: cyclic variable-value
aResult = nsnull;
NS_RELEASE(aResult);
return NS_ERROR_XSLT_BAD_RECURSION;
}
return NS_OK;
@ -269,9 +273,9 @@ txExecutionState::getVariable(PRInt32 aNamespace, nsIAtom* aLName,
rv = param->getValue(&aResult);
NS_ENSURE_SUCCESS(rv, rv);
rv = mGlobalVariableValues.bindVariable(name, aResult, PR_FALSE);
rv = mGlobalVariableValues.bindVariable(name, aResult);
if (NS_FAILED(rv)) {
aResult = nsnull;
NS_RELEASE(aResult);
return rv;
}
@ -280,8 +284,7 @@ txExecutionState::getVariable(PRInt32 aNamespace, nsIAtom* aLName,
}
// Insert a placeholdervalue to protect against recursion
rv = mGlobalVariableValues.bindVariable(name, mGlobalVarPlaceholderValue,
PR_FALSE);
rv = mGlobalVariableValues.bindVariable(name, mGlobalVarPlaceholderValue);
NS_ENSURE_SUCCESS(rv, rv);
// evaluate the global variable
@ -289,8 +292,8 @@ txExecutionState::getVariable(PRInt32 aNamespace, nsIAtom* aLName,
if (var->mExpr) {
txVariableMap* oldVars = mLocalVariables;
mLocalVariables = nsnull;
aResult = var->mExpr->evaluate(getEvalContext());
NS_ENSURE_TRUE(aResult, NS_ERROR_FAILURE);
rv = var->mExpr->evaluate(getEvalContext(), &aResult);
NS_ENSURE_SUCCESS(rv, rv);
mLocalVariables = oldVars;
}
@ -319,17 +322,17 @@ txExecutionState::getVariable(PRInt32 aNamespace, nsIAtom* aLName,
mNextInstruction = prevInstr;
rtfHandler = (txRtfHandler*)popResultHandler();
aResult = rtfHandler->createRTF();
NS_ENSURE_TRUE(aResult, NS_ERROR_OUT_OF_MEMORY);
rv = rtfHandler->getAsRTF(&aResult);
NS_ENSURE_SUCCESS(rv, rv);
}
popEvalContext();
// Remove the placeholder and insert the calculated value
mGlobalVariableValues.removeVariable(name);
rv = mGlobalVariableValues.bindVariable(name, aResult, PR_TRUE);
rv = mGlobalVariableValues.bindVariable(name, aResult);
if (NS_FAILED(rv)) {
delete aResult;
aResult = nsnull;
NS_RELEASE(aResult);
return rv;
}
@ -348,6 +351,12 @@ txExecutionState::getPrivateContext()
return this;
}
txResultRecycler*
txExecutionState::recycler()
{
return mRecycler;
}
void
txExecutionState::receiveError(const nsAString& aMsg, nsresult aRes)
{
@ -428,7 +437,7 @@ txExecutionState::popResultHandler()
nsresult
txExecutionState::pushTemplateRule(txStylesheet::ImportFrame* aFrame,
const txExpandedName& aMode,
txExpandedNameMap* aParams)
txVariableMap* aParams)
{
if (mTemplateRuleCount == mTemplateRulesBufferSize) {
PRInt32 newSize =
@ -467,12 +476,6 @@ txExecutionState::getEvalContext()
return mEvalContext;
}
txExpandedNameMap*
txExecutionState::getParamMap()
{
return mTemplateParams;
}
Node*
txExecutionState::retrieveDocument(const nsAString& uri,
const nsAString& baseUri)
@ -538,7 +541,7 @@ txExecutionState::getKeyNodes(const txExpandedName& aKeyName,
Document* aDocument,
const nsAString& aKeyValue,
PRBool aIndexIfNotFound,
const NodeSet** aResult)
NodeSet** aResult)
{
return mKeyHash.getKeyNodes(aKeyName, aDocument, aKeyValue,
aIndexIfNotFound, *this, aResult);
@ -598,13 +601,13 @@ txExecutionState::returnFromTemplate()
nsresult
txExecutionState::bindVariable(const txExpandedName& aName,
ExprResult* aValue, MBool aOwned)
txAExprResult* aValue)
{
if (!mLocalVariables) {
mLocalVariables = new txVariableMap;
NS_ENSURE_TRUE(mLocalVariables, NS_ERROR_OUT_OF_MEMORY);
}
return mLocalVariables->bindVariable(aName, aValue, aOwned);
return mLocalVariables->bindVariable(aName, aValue);
}
void
@ -614,21 +617,22 @@ txExecutionState::removeVariable(const txExpandedName& aName)
}
nsresult
txExecutionState::pushParamMap(txExpandedNameMap* aParams)
txExecutionState::pushParamMap(txVariableMap* aParams)
{
nsresult rv = mParamStack.push(mTemplateParams);
NS_ENSURE_SUCCESS(rv, rv);
mTemplateParams.forget();
mTemplateParams = aParams;
return NS_OK;
}
txExpandedNameMap*
txVariableMap*
txExecutionState::popParamMap()
{
txExpandedNameMap* oldParams = mTemplateParams;
mTemplateParams = (txExpandedNameMap*)mParamStack.pop();
txVariableMap* oldParams = mTemplateParams.forget();
mTemplateParams = (txVariableMap*)mParamStack.pop();
return oldParams;
}

Просмотреть файл

@ -101,7 +101,7 @@ public:
txStylesheet::ImportFrame* mFrame;
PRInt32 mModeNsId;
nsIAtom* mModeLocalName;
txExpandedNameMap* mParams;
txVariableMap* mParams;
};
// Stack functions
@ -115,10 +115,10 @@ public:
txAXMLEventHandler* popResultHandler();
nsresult pushTemplateRule(txStylesheet::ImportFrame* aFrame,
const txExpandedName& aMode,
txExpandedNameMap* aParams);
txVariableMap* aParams);
void popTemplateRule();
nsresult pushParamMap(txExpandedNameMap* aParams);
txExpandedNameMap* popParamMap();
nsresult pushParamMap(txVariableMap* aParams);
txVariableMap* popParamMap();
// state-getting functions
txIEvalContext* getEvalContext();
@ -126,7 +126,7 @@ public:
Node* retrieveDocument(const nsAString& uri, const nsAString& baseUri);
nsresult getKeyNodes(const txExpandedName& aKeyName, Document* aDocument,
const nsAString& aKeyValue, PRBool aIndexIfNotFound,
const NodeSet** aResult);
NodeSet** aResult);
TemplateRule* getCurrentTemplateRule();
// state-modification functions
@ -137,14 +137,14 @@ public:
void gotoInstruction(txInstruction* aNext);
void returnFromTemplate();
nsresult bindVariable(const txExpandedName& aName,
ExprResult* aValue, MBool aOwned);
txAExprResult* aValue);
void removeVariable(const txExpandedName& aName);
txAXMLEventHandler* mOutputHandler;
txAXMLEventHandler* mResultHandler;
txAOutputHandlerFactory* mOutputHandlerFactory;
txExpandedNameMap* mTemplateParams;
nsAutoPtr<txVariableMap> mTemplateParams;
nsRefPtr<txStylesheet> mStylesheet;
@ -159,7 +159,7 @@ private:
txInstruction* mNextInstruction;
txVariableMap* mLocalVariables;
txVariableMap mGlobalVariableValues;
nsAutoPtr<ExprResult> mGlobalVarPlaceholderValue;
nsRefPtr<txAExprResult> mGlobalVarPlaceholderValue;
PRInt32 mRecursionDepth;
TemplateRule* mTemplateRules;
@ -173,6 +173,7 @@ private:
txLoadedDocumentsHash mLoadedDocuments;
txKeyHash mKeyHash;
nsRefPtr<txResultRecycler> mRecycler;
static const PRInt32 kMaxRecursionDepth;
};

Просмотреть файл

@ -74,11 +74,14 @@ txFormatNumberFunctionCall::txFormatNumberFunctionCall(txStylesheet* aStylesheet
* for evaluation
* @return the result of the evaluation
*/
ExprResult* txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext)
nsresult
txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext,
txAExprResult** aResult)
{
nsresult rv = NS_OK;
*aResult = nsnull;
if (!requireParams(2, 3, aContext))
return new StringResult();
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
// Get number and format
txListIterator iter(&params);
@ -93,8 +96,7 @@ ExprResult* txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext)
nsAutoString formatQName;
evaluateToString((Expr*)iter.next(), aContext, formatQName);
rv = formatName.init(formatQName, mMappings, MB_FALSE);
if (NS_FAILED(rv))
formatName.mNamespaceID = kNameSpaceID_Unknown;
NS_ENSURE_SUCCESS(rv, rv);
}
txDecimalFormat* format = mStylesheet->getDecimalFormat(formatName);
@ -102,21 +104,24 @@ ExprResult* txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext)
nsAutoString err(NS_LITERAL_STRING("unknown decimal format for: "));
toString(err);
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
return new StringResult(err);
return NS_ERROR_XPATH_INVALID_ARG;
}
// Special cases
if (Double::isNaN(value))
return new StringResult(format->mNaN);
if (Double::isNaN(value)) {
return aContext->recycler()->getStringResult(format->mNaN, aResult);
}
if (value == Double::POSITIVE_INFINITY)
return new StringResult(format->mInfinity);
if (value == Double::POSITIVE_INFINITY) {
return aContext->recycler()->getStringResult(format->mInfinity,
aResult);
}
if (value == Double::NEGATIVE_INFINITY) {
nsAutoString res;
res.Append(format->mMinusSign);
res.Append(format->mInfinity);
return new StringResult(res);
return aContext->recycler()->getStringResult(res, aResult);
}
// Value is a normal finite number
@ -172,7 +177,7 @@ ExprResult* txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext)
toString(err);
aContext->receiveError(err,
NS_ERROR_XPATH_INVALID_ARG);
return new StringResult(err);
return NS_ERROR_XPATH_INVALID_ARG;
}
}
else if (c == format->mPerMille) {
@ -183,7 +188,7 @@ ExprResult* txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext)
toString(err);
aContext->receiveError(err,
NS_ERROR_XPATH_INVALID_ARG);
return new StringResult(err);
return NS_ERROR_XPATH_INVALID_ARG;
}
}
else if (c == format->mDecimalSeparator ||
@ -266,9 +271,8 @@ ExprResult* txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext)
groupSize == 0) {
nsAutoString err(INVALID_PARAM_VALUE);
toString(err);
aContext->receiveError(err,
NS_ERROR_XPATH_INVALID_ARG);
return new StringResult(err);
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
return NS_ERROR_XPATH_INVALID_ARG;
}
@ -289,10 +293,7 @@ ExprResult* txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext)
bufsize = 1 + 30;
char* buf = new char[bufsize];
if (!buf) {
//XXX ErrorReport: out of memory
return new StringResult;
}
NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
PRIntn bufIntDigits, sign;
char* endp;
@ -391,7 +392,7 @@ ExprResult* txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext)
// Build suffix
res.Append(suffix);
return new StringResult(res);
return aContext->recycler()->getStringResult(res, aResult);
} //-- evaluate
nsresult txFormatNumberFunctionCall::getNameAtom(nsIAtom** aAtom)

Просмотреть файл

@ -64,74 +64,69 @@ FunctionAvailableFunctionCall::FunctionAvailableFunctionCall(txNamespaceMap* aMa
* @return the result of the evaluation
* @see FunctionCall.h
**/
ExprResult* FunctionAvailableFunctionCall::evaluate(txIEvalContext* aContext)
nsresult
FunctionAvailableFunctionCall::evaluate(txIEvalContext* aContext,
txAExprResult** aResult)
{
ExprResult* result = nsnull;
if (requireParams(1, 1, aContext)) {
txListIterator iter(&params);
Expr* param = (Expr*)iter.next();
ExprResult* exprResult = param->evaluate(aContext);
if (exprResult &&
exprResult->getResultType() == ExprResult::STRING) {
nsAutoString property;
exprResult->stringValue(property);
txExpandedName qname;
nsresult rv = qname.init(property, mMappings, MB_FALSE);
if (NS_SUCCEEDED(rv) &&
qname.mNamespaceID == kNameSpaceID_None &&
(qname.mLocalName == txXPathAtoms::boolean ||
qname.mLocalName == txXPathAtoms::ceiling ||
qname.mLocalName == txXPathAtoms::concat ||
qname.mLocalName == txXPathAtoms::contains ||
qname.mLocalName == txXPathAtoms::count ||
qname.mLocalName == txXPathAtoms::_false ||
qname.mLocalName == txXPathAtoms::floor ||
qname.mLocalName == txXPathAtoms::id ||
qname.mLocalName == txXPathAtoms::lang ||
qname.mLocalName == txXPathAtoms::last ||
qname.mLocalName == txXPathAtoms::localName ||
qname.mLocalName == txXPathAtoms::name ||
qname.mLocalName == txXPathAtoms::namespaceUri ||
qname.mLocalName == txXPathAtoms::normalizeSpace ||
qname.mLocalName == txXPathAtoms::_not ||
qname.mLocalName == txXPathAtoms::number ||
qname.mLocalName == txXPathAtoms::position ||
qname.mLocalName == txXPathAtoms::round ||
qname.mLocalName == txXPathAtoms::startsWith ||
qname.mLocalName == txXPathAtoms::string ||
qname.mLocalName == txXPathAtoms::stringLength ||
qname.mLocalName == txXPathAtoms::substring ||
qname.mLocalName == txXPathAtoms::substringAfter ||
qname.mLocalName == txXPathAtoms::substringBefore ||
qname.mLocalName == txXPathAtoms::sum ||
qname.mLocalName == txXPathAtoms::translate ||
qname.mLocalName == txXPathAtoms::_true ||
qname.mLocalName == txXSLTAtoms::current ||
qname.mLocalName == txXSLTAtoms::document ||
qname.mLocalName == txXSLTAtoms::elementAvailable ||
qname.mLocalName == txXSLTAtoms::formatNumber ||
qname.mLocalName == txXSLTAtoms::functionAvailable ||
qname.mLocalName == txXSLTAtoms::generateId ||
qname.mLocalName == txXSLTAtoms::key ||
// qname.mLocalName == txXSLTAtoms::unparsedEntityUri ||
qname.mLocalName == txXSLTAtoms::systemProperty)) {
result = new BooleanResult(MB_TRUE);
}
}
else {
NS_NAMED_LITERAL_STRING(err, "Invalid argument passed to function-available, expecting String");
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
result = new StringResult(err);
}
delete exprResult;
*aResult = nsnull;
if (!requireParams(1, 1, aContext)) {
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
}
if (!result) {
result = new BooleanResult(MB_FALSE);
}
txListIterator iter(&params);
Expr* param = (Expr*)iter.next();
nsRefPtr<txAExprResult> exprResult;
nsresult rv = param->evaluate(aContext, getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString property;
exprResult->stringValue(property);
txExpandedName qname;
rv = qname.init(property, mMappings, MB_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
PRBool val = qname.mNamespaceID == kNameSpaceID_None &&
(qname.mLocalName == txXPathAtoms::boolean ||
qname.mLocalName == txXPathAtoms::ceiling ||
qname.mLocalName == txXPathAtoms::concat ||
qname.mLocalName == txXPathAtoms::contains ||
qname.mLocalName == txXPathAtoms::count ||
qname.mLocalName == txXPathAtoms::_false ||
qname.mLocalName == txXPathAtoms::floor ||
qname.mLocalName == txXPathAtoms::id ||
qname.mLocalName == txXPathAtoms::lang ||
qname.mLocalName == txXPathAtoms::last ||
qname.mLocalName == txXPathAtoms::localName ||
qname.mLocalName == txXPathAtoms::name ||
qname.mLocalName == txXPathAtoms::namespaceUri ||
qname.mLocalName == txXPathAtoms::normalizeSpace ||
qname.mLocalName == txXPathAtoms::_not ||
qname.mLocalName == txXPathAtoms::number ||
qname.mLocalName == txXPathAtoms::position ||
qname.mLocalName == txXPathAtoms::round ||
qname.mLocalName == txXPathAtoms::startsWith ||
qname.mLocalName == txXPathAtoms::string ||
qname.mLocalName == txXPathAtoms::stringLength ||
qname.mLocalName == txXPathAtoms::substring ||
qname.mLocalName == txXPathAtoms::substringAfter ||
qname.mLocalName == txXPathAtoms::substringBefore ||
qname.mLocalName == txXPathAtoms::sum ||
qname.mLocalName == txXPathAtoms::translate ||
qname.mLocalName == txXPathAtoms::_true ||
qname.mLocalName == txXSLTAtoms::current ||
qname.mLocalName == txXSLTAtoms::document ||
qname.mLocalName == txXSLTAtoms::elementAvailable ||
qname.mLocalName == txXSLTAtoms::formatNumber ||
qname.mLocalName == txXSLTAtoms::functionAvailable ||
qname.mLocalName == txXSLTAtoms::generateId ||
qname.mLocalName == txXSLTAtoms::key ||
//qname.mLocalName == txXSLTAtoms::unparsedEntityUri ||
qname.mLocalName == txXSLTAtoms::systemProperty);
aContext->recycler()->getBoolResult(val, aResult);
return NS_OK;
return result;
}
nsresult FunctionAvailableFunctionCall::getNameAtom(nsIAtom** aAtom)

Просмотреть файл

@ -53,10 +53,13 @@ GenerateIdFunctionCall::GenerateIdFunctionCall()
* @return the result of the evaluation
* @see FunctionCall.h
**/
ExprResult* GenerateIdFunctionCall::evaluate(txIEvalContext* aContext)
nsresult
GenerateIdFunctionCall::evaluate(txIEvalContext* aContext,
txAExprResult** aResult)
{
*aResult = nsnull;
if (!requireParams(0, 1, aContext))
return new StringResult();
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
Node* node = 0;
@ -65,24 +68,26 @@ ExprResult* GenerateIdFunctionCall::evaluate(txIEvalContext* aContext)
txListIterator iter(&params);
Expr* param = (Expr*)iter.next();
ExprResult* exprResult = param->evaluate(aContext);
if (!exprResult)
return 0;
nsRefPtr<txAExprResult> exprResult;
nsresult rv = param->evaluate(aContext, getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, rv);
if (exprResult->getResultType() != ExprResult::NODESET) {
if (exprResult->getResultType() != txAExprResult::NODESET) {
NS_NAMED_LITERAL_STRING(err, "Invalid argument passed to generate-id(), expecting NodeSet");
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
delete exprResult;
return new StringResult(err);
aContext->receiveError(err, NS_ERROR_XSLT_NODESET_EXPECTED);
return NS_ERROR_XSLT_NODESET_EXPECTED;
}
NodeSet* nodes = (NodeSet*) exprResult;
if (nodes->isEmpty())
return new StringResult();
NodeSet* nodes = NS_STATIC_CAST(NodeSet*,
NS_STATIC_CAST(txAExprResult*,
exprResult));
if (nodes->isEmpty()) {
aContext->recycler()->getEmptyStringResult(aResult);
return NS_OK;
}
node = nodes->get(0);
delete exprResult;
}
else {
node = aContext->getContextNode();
@ -91,7 +96,8 @@ ExprResult* GenerateIdFunctionCall::evaluate(txIEvalContext* aContext)
// generate id for selected node
char buf[22];
PR_snprintf(buf, 21, printfFmt, node);
return new StringResult(NS_ConvertASCIItoUCS2(buf));
return aContext->recycler()->getStringResult(NS_ConvertASCIItoUCS2(buf),
aResult);
}
nsresult GenerateIdFunctionCall::getNameAtom(nsIAtom** aAtom)

Просмотреть файл

@ -134,14 +134,13 @@ txAttribute::txAttribute(nsAutoPtr<Expr> aName, nsAutoPtr<Expr> aNamespace,
nsresult
txAttribute::execute(txExecutionState& aEs)
{
nsresult rv = NS_OK;
ExprResult* exprRes = mName->evaluate(aEs.getEvalContext());
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> exprRes;
nsresult rv = mName->evaluate(aEs.getEvalContext(),
getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString name;
exprRes->stringValue(name);
delete exprRes;
if (!XMLUtils::isValidQName(name) ||
TX_StringEqualsAtom(name, txXMLAtoms::xmlns)) {
@ -155,12 +154,12 @@ txAttribute::execute(txExecutionState& aEs)
PRInt32 nsId = kNameSpaceID_None;
if (!name.IsEmpty()) {
if (mNamespace) {
exprRes = mNamespace->evaluate(aEs.getEvalContext());
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
rv = mNamespace->evaluate(aEs.getEvalContext(),
getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString nspace;
exprRes->stringValue(nspace);
delete exprRes;
if (!nspace.IsEmpty()) {
#ifdef TX_EXE
@ -186,13 +185,12 @@ txAttribute::execute(txExecutionState& aEs)
name.Cut(0, 6);
}
txTextHandler* handler =
NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler());
nsAutoPtr<txTextHandler> handler(
NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler()));
if (!name.IsEmpty()) {
// add attribute if everything was ok
aEs.mResultHandler->attribute(name, nsId, handler->mValue);
}
delete handler;
return NS_OK;
}
@ -224,10 +222,10 @@ txCheckParam::execute(txExecutionState& aEs)
{
nsresult rv = NS_OK;
if (aEs.mTemplateParams) {
ExprResult* exprRes =
NS_STATIC_CAST(ExprResult*, aEs.mTemplateParams->get(mName));
nsRefPtr<txAExprResult> exprRes;
aEs.mTemplateParams->getVariable(mName, getter_AddRefs(exprRes));
if (exprRes) {
rv = aEs.bindVariable(mName, exprRes, MB_FALSE);
rv = aEs.bindVariable(mName, exprRes);
NS_ENSURE_SUCCESS(rv, rv);
aEs.gotoInstruction(mBailTarget);
@ -247,13 +245,14 @@ txConditionalGoto::txConditionalGoto(nsAutoPtr<Expr> aCondition,
nsresult
txConditionalGoto::execute(txExecutionState& aEs)
{
ExprResult* exprRes = mCondition->evaluate(aEs.getEvalContext());
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> exprRes;
nsresult rv = mCondition->evaluate(aEs.getEvalContext(),
getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
if (!exprRes->booleanValue()) {
aEs.gotoInstruction(mTarget);
}
delete exprRes;
return NS_OK;
}
@ -261,8 +260,8 @@ txConditionalGoto::execute(txExecutionState& aEs)
nsresult
txComment::execute(txExecutionState& aEs)
{
txTextHandler* handler =
NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler());
nsAutoPtr<txTextHandler> handler(
NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler()));
PRUint32 length = handler->mValue.Length();
PRInt32 pos = 0;
while ((pos = handler->mValue.FindChar('-', (PRUint32)pos)) != kNotFound) {
@ -274,7 +273,6 @@ txComment::execute(txExecutionState& aEs)
}
aEs.mResultHandler->comment(handler->mValue);
delete handler;
return NS_OK;
}
@ -428,34 +426,33 @@ txCopyOf::txCopyOf(nsAutoPtr<Expr> aSelect)
nsresult
txCopyOf::execute(txExecutionState& aEs)
{
nsresult rv = NS_OK;
ExprResult* exprRes = mSelect->evaluate(aEs.getEvalContext());
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> exprRes;
nsresult rv = mSelect->evaluate(aEs.getEvalContext(),
getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
switch (exprRes->getResultType()) {
case ExprResult::NODESET:
case txAExprResult::NODESET:
{
NodeSet* nodes = NS_STATIC_CAST(NodeSet*, exprRes);
NodeSet* nodes = NS_STATIC_CAST(NodeSet*,
NS_STATIC_CAST(txAExprResult*,
exprRes));
int i;
for (i = 0; i < nodes->size(); ++i) {
Node* node = nodes->get(i);
rv = copyNode(node, aEs);
if (NS_FAILED(rv)) {
delete exprRes;
return rv;
}
NS_ENSURE_SUCCESS(rv, rv);
}
break;
}
case ExprResult::RESULT_TREE_FRAGMENT:
case txAExprResult::RESULT_TREE_FRAGMENT:
{
txResultTreeFragment* rtf = NS_STATIC_CAST(txResultTreeFragment*,
exprRes);
txResultTreeFragment* rtf =
NS_STATIC_CAST(txResultTreeFragment*,
NS_STATIC_CAST(txAExprResult*, exprRes));
rv = rtf->flushToHandler(aEs.mResultHandler);
if (NS_FAILED(rv)) {
delete exprRes;
return rv;
}
NS_ENSURE_SUCCESS(rv, rv);
break;
}
default:
@ -469,8 +466,6 @@ txCopyOf::execute(txExecutionState& aEs)
}
}
delete exprRes;
return NS_OK;
}
@ -575,8 +570,10 @@ txLREAttribute::execute(txExecutionState& aEs)
mLocalName->ToString(nodeName);
}
nsAutoPtr<ExprResult> exprRes(mValue->evaluate(aEs.getEvalContext()));
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> exprRes;
nsresult rv = mValue->evaluate(aEs.getEvalContext(),
getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
nsAString* value = exprRes->stringValuePointer();
if (value) {
@ -599,8 +596,8 @@ txMessage::txMessage(PRBool aTerminate)
nsresult
txMessage::execute(txExecutionState& aEs)
{
txTextHandler* handler =
NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler());
nsAutoPtr<txTextHandler> handler(
NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler()));
nsCOMPtr<nsIConsoleService> consoleSvc =
do_GetService("@mozilla.org/consoleservice;1");
@ -609,7 +606,6 @@ txMessage::execute(txExecutionState& aEs)
logString.Append(handler->mValue);
consoleSvc->LogStringMessage(logString.get());
}
delete handler;
return mTerminate ? NS_ERROR_XSLT_ABORTED : NS_OK;
}
@ -655,22 +651,22 @@ txProcessingInstruction::txProcessingInstruction(nsAutoPtr<Expr> aName)
nsresult
txProcessingInstruction::execute(txExecutionState& aEs)
{
txTextHandler* handler =
NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler());
nsAutoPtr<txTextHandler> handler(
NS_STATIC_CAST(txTextHandler*, aEs.popResultHandler()));
XMLUtils::normalizePIValue(handler->mValue);
ExprResult* exprRes = mName->evaluate(aEs.getEvalContext());
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> exprRes;
nsresult rv = mName->evaluate(aEs.getEvalContext(),
getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString name;
exprRes->stringValue(name);
delete exprRes;
// Check name validity (must be valid NCName and a PITarget)
// XXX Need to check for NCName and PITarget
if (!XMLUtils::isValidQName(name)) {
// XXX ErrorReport: bad PI-target
delete handler;
return NS_ERROR_FAILURE;
}
@ -696,17 +692,18 @@ txPushNewContext::~txPushNewContext()
nsresult
txPushNewContext::execute(txExecutionState& aEs)
{
nsresult rv = NS_OK;
ExprResult* exprRes = mSelect->evaluate(aEs.getEvalContext());
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> exprRes;
nsresult rv = mSelect->evaluate(aEs.getEvalContext(),
getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
if (exprRes->getResultType() != ExprResult::NODESET) {
delete exprRes;
if (exprRes->getResultType() != txAExprResult::NODESET) {
// XXX ErrorReport: nodeset expected
return NS_ERROR_XSLT_NODESET_EXPECTED;
}
NodeSet* nodes = NS_STATIC_CAST(NodeSet*, exprRes);
NodeSet* nodes =
NS_STATIC_CAST(NodeSet*, NS_STATIC_CAST(txAExprResult*, exprRes));
if (nodes->isEmpty()) {
aEs.gotoInstruction(mBailTarget);
@ -727,11 +724,8 @@ txPushNewContext::execute(txExecutionState& aEs)
rv = sorter.sortNodeSet(nodes, &aEs);
NS_ENSURE_SUCCESS(rv, rv);
txNodeSetContext* context = new txOwningNodeSetContext(nodes, &aEs);
if (!context) {
delete exprRes;
return NS_ERROR_OUT_OF_MEMORY;
}
txNodeSetContext* context = new txNodeSetContext(nodes, &aEs);
NS_ENSURE_TRUE(context, NS_ERROR_OUT_OF_MEMORY);
context->next();
@ -851,29 +845,27 @@ txSetParam::txSetParam(const txExpandedName& aName, nsAutoPtr<Expr> aValue)
nsresult
txSetParam::execute(txExecutionState& aEs)
{
nsresult rv = NS_OK;
if (!aEs.mTemplateParams) {
aEs.mTemplateParams = new txExpandedNameMap(PR_TRUE);
aEs.mTemplateParams = new txVariableMap;
NS_ENSURE_TRUE(aEs.mTemplateParams, NS_ERROR_OUT_OF_MEMORY);
}
ExprResult* exprRes;
nsRefPtr<txAExprResult> exprRes;
if (mValue) {
exprRes = mValue->evaluate(aEs.getEvalContext());
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
rv = mValue->evaluate(aEs.getEvalContext(),
getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
}
else {
txRtfHandler* rtfHandler =
NS_STATIC_CAST(txRtfHandler*, aEs.popResultHandler());
exprRes = rtfHandler->createRTF();
delete rtfHandler;
NS_ENSURE_TRUE(exprRes, NS_ERROR_OUT_OF_MEMORY);
nsAutoPtr<txRtfHandler> rtfHandler(
NS_STATIC_CAST(txRtfHandler*, aEs.popResultHandler()));
rv = rtfHandler->getAsRTF(getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
}
nsresult rv = aEs.mTemplateParams->add(mName, exprRes);
if (NS_FAILED(rv)) {
delete exprRes;
return rv;
}
rv = aEs.mTemplateParams->bindVariable(mName, exprRes);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
@ -887,26 +879,20 @@ txSetVariable::txSetVariable(const txExpandedName& aName,
nsresult
txSetVariable::execute(txExecutionState& aEs)
{
ExprResult* exprRes;
nsresult rv = NS_OK;
nsRefPtr<txAExprResult> exprRes;
if (mValue) {
exprRes = mValue->evaluate(aEs.getEvalContext());
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
rv = mValue->evaluate(aEs.getEvalContext(), getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
}
else {
txRtfHandler* rtfHandler =
NS_STATIC_CAST(txRtfHandler*, aEs.popResultHandler());
exprRes = rtfHandler->createRTF();
delete rtfHandler;
NS_ENSURE_TRUE(exprRes, NS_ERROR_OUT_OF_MEMORY);
nsAutoPtr<txRtfHandler> rtfHandler(
NS_STATIC_CAST(txRtfHandler*, aEs.popResultHandler()));
rv = rtfHandler->getAsRTF(getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
}
nsresult rv = aEs.bindVariable(mName, exprRes, MB_TRUE);
if (NS_FAILED(rv)) {
delete exprRes;
return rv;
}
return NS_OK;
return aEs.bindVariable(mName, exprRes);
}
txStartElement::txStartElement(nsAutoPtr<Expr> aName,
@ -921,14 +907,13 @@ txStartElement::txStartElement(nsAutoPtr<Expr> aName,
nsresult
txStartElement::execute(txExecutionState& aEs)
{
nsresult rv = NS_OK;
ExprResult* exprRes = mName->evaluate(aEs.getEvalContext());
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> exprRes;
nsresult rv = mName->evaluate(aEs.getEvalContext(),
getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString name;
exprRes->stringValue(name);
delete exprRes;
if (!XMLUtils::isValidQName(name)) {
// tunkate name to indicate failure
@ -938,12 +923,12 @@ txStartElement::execute(txExecutionState& aEs)
PRInt32 nsId = kNameSpaceID_None;
if (!name.IsEmpty()) {
if (mNamespace) {
exprRes = mNamespace->evaluate(aEs.getEvalContext());
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
rv = mNamespace->evaluate(aEs.getEvalContext(),
getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString nspace;
exprRes->stringValue(nspace);
delete exprRes;
if (!nspace.IsEmpty()) {
#ifdef TX_EXE
@ -1044,8 +1029,10 @@ txValueOf::txValueOf(nsAutoPtr<Expr> aExpr, PRBool aDOE)
nsresult
txValueOf::execute(txExecutionState& aEs)
{
nsAutoPtr<ExprResult> exprRes(mExpr->evaluate(aEs.getEvalContext()));
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> exprRes;
nsresult rv = mExpr->evaluate(aEs.getEvalContext(),
getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
nsAString* value = exprRes->stringValuePointer();
if (value) {
@ -1061,6 +1048,5 @@ txValueOf::execute(txExecutionState& aEs)
}
}
return NS_OK;
}

Просмотреть файл

@ -69,7 +69,8 @@ public:
struct txKeyValueHashEntry : public PLDHashEntryHdr
{
txKeyValueHashEntry(const void* aKey)
: mKey(*NS_STATIC_CAST(const txKeyValueHashKey*, aKey))
: mKey(*NS_STATIC_CAST(const txKeyValueHashKey*, aKey)),
mNodeSet(new NodeSet(nsnull))
{
}
@ -79,7 +80,7 @@ struct txKeyValueHashEntry : public PLDHashEntryHdr
static PLDHashNumber HashKey(const void* aKey);
txKeyValueHashKey mKey;
NodeSet mNodeSet;
nsRefPtr<NodeSet> mNodeSet;
};
DECL_DHASH_WRAPPER(txKeyValueHash, txKeyValueHashEntry, txKeyValueHashKey&);
@ -206,7 +207,7 @@ public:
const nsAString& aKeyValue,
PRBool aIndexIfNotFound,
txExecutionState& aEs,
const NodeSet** aResult);
NodeSet** aResult);
private:
// Hash of all indexed key-values
@ -217,6 +218,9 @@ private:
// Map of txXSLKeys
const txExpandedNameMap& mKeys;
// Empty nodeset returned if no key is found
nsRefPtr<NodeSet> mEmptyNodeSet;
};

Просмотреть файл

@ -49,34 +49,26 @@ txKeyFunctionCall::txKeyFunctionCall(txNamespaceMap* aMappings)
* for evaluation
* @return the result of the evaluation
*/
ExprResult* txKeyFunctionCall::evaluate(txIEvalContext* aContext)
nsresult
txKeyFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
if (!aContext || !requireParams(2, 2, aContext))
return new StringResult(NS_LITERAL_STRING("error"));
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
txExecutionState* es =
NS_STATIC_CAST(txExecutionState*, aContext->getPrivateContext());
NodeSet* res = new NodeSet;
if (!res) {
// ErrorReport: out of memory
return 0;
}
txListIterator iter(&params);
nsAutoString keyQName;
evaluateToString((Expr*)iter.next(), aContext, keyQName);
txExpandedName keyName;
nsresult rv = keyName.init(keyQName, mMappings, PR_FALSE);
if (NS_FAILED(rv)) {
delete res;
return new StringResult(NS_LITERAL_STRING("error"));
}
NS_ENSURE_SUCCESS(rv, rv);
ExprResult* exprResult = ((Expr*)iter.next())->evaluate(aContext);
if (!exprResult)
return res;
nsRefPtr<txAExprResult> exprResult;
rv = ((Expr*)iter.next())->evaluate(aContext, getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, rv);
Document* contextDoc;
Node* contextNode = aContext->getContextNode();
@ -85,40 +77,40 @@ ExprResult* txKeyFunctionCall::evaluate(txIEvalContext* aContext)
else
contextDoc = contextNode->getOwnerDocument();
if (exprResult->getResultType() == ExprResult::NODESET) {
NodeSet* nodeSet = (NodeSet*) exprResult;
nsRefPtr<NodeSet> res;
NodeSet* nodeSet;
if (exprResult->getResultType() == txAExprResult::NODESET &&
(nodeSet = NS_STATIC_CAST(NodeSet*,
NS_STATIC_CAST(txAExprResult*,
exprResult)))->size() > 1) {
rv = aContext->recycler()->getNodeSet(getter_AddRefs(res));
NS_ENSURE_SUCCESS(rv, rv);
int i;
for (i = 0; i < nodeSet->size(); ++i) {
nsAutoString val;
XMLDOMUtils::getNodeValue(nodeSet->get(i), val);
const NodeSet* nodes = 0;
rv = es->getKeyNodes(keyName, contextDoc, val, i == 0, &nodes);
if (NS_FAILED(rv)) {
delete res;
delete exprResult;
return new StringResult(NS_LITERAL_STRING("error"));
}
if (nodes) {
res->add(nodes);
}
nsRefPtr<NodeSet> nodes;
rv = es->getKeyNodes(keyName, contextDoc, val, i == 0,
getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
res->add(nodes);
}
}
else {
nsAutoString val;
exprResult->stringValue(val);
const NodeSet* nodes = 0;
rv = es->getKeyNodes(keyName, contextDoc, val, PR_TRUE, &nodes);
if (NS_FAILED(rv)) {
delete res;
delete exprResult;
return new StringResult(NS_LITERAL_STRING("error"));
}
if (nodes) {
res->append(nodes);
}
rv = es->getKeyNodes(keyName, contextDoc, val, PR_TRUE,
getter_AddRefs(res));
NS_ENSURE_SUCCESS(rv, rv);
}
delete exprResult;
return res;
*aResult = res;
NS_ADDREF(*aResult);
return NS_OK;
}
nsresult txKeyFunctionCall::getNameAtom(nsIAtom** aAtom)
@ -201,7 +193,7 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName,
const nsAString& aKeyValue,
PRBool aIndexIfNotFound,
txExecutionState& aEs,
const NodeSet** aResult)
NodeSet** aResult)
{
NS_ENSURE_TRUE(mKeyValues.mHashTable.ops && mIndexedKeys.mHashTable.ops,
NS_ERROR_OUT_OF_MEMORY);
@ -210,7 +202,8 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName,
txKeyValueHashKey valueKey(aKeyName, aDocument, aKeyValue);
txKeyValueHashEntry* valueEntry = mKeyValues.GetEntry(valueKey);
if (valueEntry) {
*aResult = &valueEntry->mNodeSet;
*aResult = valueEntry->mNodeSet;
NS_ADDREF(*aResult);
return NS_OK;
}
@ -221,6 +214,8 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName,
if (!aIndexIfNotFound) {
// If aIndexIfNotFound is set then the caller knows this key is
// indexed, so don't bother investigating.
*aResult = mEmptyNodeSet;
NS_ADDREF(*aResult);
return NS_OK;
}
@ -230,8 +225,9 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName,
if (indexEntry->mIndexed) {
// The key was indexed and apparently didn't contain this value so
// return null.
// return the empty nodeset.
*aResult = mEmptyNodeSet;
NS_ADDREF(*aResult);
return NS_OK;
}
@ -250,7 +246,12 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName,
// Now that the key is indexed we can get its value.
valueEntry = mKeyValues.GetEntry(valueKey);
if (valueEntry) {
*aResult = &valueEntry->mNodeSet;
*aResult = valueEntry->mNodeSet;
NS_ADDREF(*aResult);
}
else {
*aResult = mEmptyNodeSet;
NS_ADDREF(*aResult);
}
return NS_OK;
@ -262,7 +263,13 @@ txKeyHash::init()
nsresult rv = mKeyValues.Init(8);
NS_ENSURE_SUCCESS(rv, rv);
return mIndexedKeys.Init(1);
rv = mIndexedKeys.Init(1);
NS_ENSURE_SUCCESS(rv, rv);
mEmptyNodeSet = new NodeSet(nsnull);
NS_ENSURE_TRUE(mEmptyNodeSet, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
/**
@ -374,23 +381,30 @@ nsresult txXSLKey::testNode(Node* aNode, txKeyValueHashKey& aKey,
rv = aEs.pushEvalContext(&evalContext);
NS_ENSURE_SUCCESS(rv, rv);
ExprResult* exprResult = key->useExpr->evaluate(&evalContext);
nsRefPtr<txAExprResult> exprResult;
rv = key->useExpr->evaluate(&evalContext,
getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, rv);
aEs.popEvalContext();
if (exprResult->getResultType() == ExprResult::NODESET) {
NodeSet* res = (NodeSet*)exprResult;
if (exprResult->getResultType() == txAExprResult::NODESET) {
NodeSet* res = NS_STATIC_CAST(NodeSet*,
NS_STATIC_CAST(txAExprResult*,
exprResult));
for (int i=0; i<res->size(); i++) {
val.Truncate();
XMLDOMUtils::getNodeValue(res->get(i), val);
aKey.mKeyValue.Assign(val);
txKeyValueHashEntry* entry = aKeyValueHash.AddEntry(aKey);
NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_TRUE(entry && entry->mNodeSet,
NS_ERROR_OUT_OF_MEMORY);
if (entry->mNodeSet.isEmpty() ||
entry->mNodeSet.get(entry->mNodeSet.size() - 1) !=
if (entry->mNodeSet->isEmpty() ||
entry->mNodeSet->get(entry->mNodeSet->size() - 1) !=
aNode) {
entry->mNodeSet.append(aNode);
entry->mNodeSet->append(aNode);
}
}
}
@ -399,15 +413,15 @@ nsresult txXSLKey::testNode(Node* aNode, txKeyValueHashKey& aKey,
aKey.mKeyValue.Assign(val);
txKeyValueHashEntry* entry = aKeyValueHash.AddEntry(aKey);
NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_TRUE(entry && entry->mNodeSet,
NS_ERROR_OUT_OF_MEMORY);
if (entry->mNodeSet.isEmpty() ||
entry->mNodeSet.get(entry->mNodeSet.size()-1) !=
if (entry->mNodeSet->isEmpty() ||
entry->mNodeSet->get(entry->mNodeSet->size() - 1) !=
aNode) {
entry->mNodeSet.append(aNode);
entry->mNodeSet->append(aNode);
}
}
delete exprResult;
}
}

Просмотреть файл

@ -938,7 +938,7 @@ txMozillaXSLTProcessor::ContentRemoved(nsIDocument* aDocument,
/* static*/
nsresult
txVariable::Convert(nsIVariant *aValue, ExprResult** aResult)
txVariable::Convert(nsIVariant *aValue, txAExprResult** aResult)
{
*aResult = nsnull;
@ -961,8 +961,10 @@ txVariable::Convert(nsIVariant *aValue, ExprResult** aResult)
nsresult rv = aValue->GetAsDouble(&value);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = new NumberResult(value);
NS_ENSURE_TRUE(aResult, NS_ERROR_OUT_OF_MEMORY);
*aResult = new NumberResult(value, nsnull);
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aResult);
return NS_OK;
}
@ -975,7 +977,9 @@ txVariable::Convert(nsIVariant *aValue, ExprResult** aResult)
NS_ENSURE_SUCCESS(rv, rv);
*aResult = new BooleanResult(value);
NS_ENSURE_TRUE(aResult, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aResult);
return NS_OK;
}
@ -996,8 +1000,10 @@ txVariable::Convert(nsIVariant *aValue, ExprResult** aResult)
nsresult rv = aValue->GetAsAString(value);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = new StringResult(value);
NS_ENSURE_TRUE(aResult, NS_ERROR_OUT_OF_MEMORY);
*aResult = new StringResult(value, nsnull);
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aResult);
return NS_OK;
}

Просмотреть файл

@ -74,20 +74,17 @@ public:
mTxValue(nsnull)
{
}
~txVariable()
{
delete mTxValue;
}
nsresult getValue(ExprResult** aValue)
nsresult getValue(txAExprResult** aValue)
{
NS_ASSERTION(mValue, "variablevalue is null");
if (!mTxValue) {
nsresult rv = Convert(mValue, &mTxValue);
nsresult rv = Convert(mValue, getter_AddRefs(mTxValue));
NS_ENSURE_SUCCESS(rv, rv);
}
*aValue = mTxValue;
NS_ADDREF(*aValue);
return NS_OK;
}
@ -101,15 +98,14 @@ public:
{
NS_ASSERTION(aValue, "setting variablevalue to null");
mValue = aValue;
delete mTxValue;
mTxValue = nsnull;
}
private:
static nsresult Convert(nsIVariant *aValue, ExprResult** aResult);
static nsresult Convert(nsIVariant *aValue, txAExprResult** aResult);
nsCOMPtr<nsIVariant> mValue;
ExprResult* mTxValue;
nsRefPtr<txAExprResult> mTxValue;
};
/**

Просмотреть файл

@ -72,6 +72,7 @@ txNodeSorter::addSortElement(Expr* aSelectExpr, Expr* aLangExpr,
{
SortKey* key = new SortKey;
NS_ENSURE_TRUE(key, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = NS_OK;
// Select
key->mExpr = aSelectExpr;
@ -79,12 +80,12 @@ txNodeSorter::addSortElement(Expr* aSelectExpr, Expr* aLangExpr,
// Order
MBool ascending = MB_TRUE;
if (aOrderExpr) {
ExprResult* exprRes = aOrderExpr->evaluate(aContext);
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> exprRes;
rv = aOrderExpr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString attrValue;
exprRes->stringValue(attrValue);
delete exprRes;
if (TX_StringEqualsAtom(attrValue, txXSLTAtoms::descending)) {
ascending = MB_FALSE;
@ -100,11 +101,11 @@ txNodeSorter::addSortElement(Expr* aSelectExpr, Expr* aLangExpr,
// Create comparator depending on datatype
nsAutoString dataType;
if (aDataTypeExpr) {
ExprResult* exprRes = aDataTypeExpr->evaluate(aContext);
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> exprRes;
rv = aDataTypeExpr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
exprRes->stringValue(dataType);
delete exprRes;
}
if (!aDataTypeExpr || TX_StringEqualsAtom(dataType, txXSLTAtoms::text)) {
@ -113,22 +114,22 @@ txNodeSorter::addSortElement(Expr* aSelectExpr, Expr* aLangExpr,
// Language
nsAutoString lang;
if (aLangExpr) {
ExprResult* exprRes = aLangExpr->evaluate(aContext);
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> exprRes;
rv = aLangExpr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
exprRes->stringValue(lang);
delete exprRes;
}
// Case-order
MBool upperFirst = PR_FALSE;
if (aCaseOrderExpr) {
ExprResult* exprRes = aCaseOrderExpr->evaluate(aContext);
NS_ENSURE_TRUE(exprRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> exprRes;
rv = aCaseOrderExpr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString attrValue;
exprRes->stringValue(attrValue);
delete exprRes;
if (TX_StringEqualsAtom(attrValue, txXSLTAtoms::upperFirst)) {
upperFirst = PR_TRUE;
@ -218,6 +219,7 @@ int txNodeSorter::compareNodes(SortableNode* aSNode1,
txExecutionState* aEs)
{
txListIterator iter(&mSortKeys);
nsresult rv = NS_OK;
int i;
// Step through each key until a difference is found
@ -227,34 +229,30 @@ int txNodeSorter::compareNodes(SortableNode* aSNode1,
if (!aSNode1->mSortValues[i]) {
txForwardContext evalContext(aEs->getEvalContext(), aSNode1->mNode, aNodes);
aEs->pushEvalContext(&evalContext);
ExprResult* res = key->mExpr->evaluate(&evalContext);
nsRefPtr<txAExprResult> res;
rv = key->mExpr->evaluate(&evalContext, getter_AddRefs(res));
NS_ENSURE_SUCCESS(rv, -1);
aEs->popEvalContext();
if (!res) {
// XXX ErrorReport
return -1;
}
aSNode1->mSortValues[i] = key->mComparator->createSortableValue(res);
if (!aSNode1->mSortValues[i]) {
// XXX ErrorReport
return -1;
}
delete res;
}
if (!aSNode2->mSortValues[i]) {
txForwardContext evalContext(aEs->getEvalContext(), aSNode2->mNode, aNodes);
aEs->pushEvalContext(&evalContext);
ExprResult* res = key->mExpr->evaluate(&evalContext);
nsRefPtr<txAExprResult> res;
rv = key->mExpr->evaluate(&evalContext, getter_AddRefs(res));
NS_ENSURE_SUCCESS(rv, -1);
aEs->popEvalContext();
if (!res) {
// XXX ErrorReport
return -1;
}
aSNode2->mSortValues[i] = key->mComparator->createSortableValue(res);
if (!aSNode2->mSortValues[i]) {
// XXX ErrorReport
return -1;
}
delete res;
}
// Compare node values

Просмотреть файл

@ -39,8 +39,8 @@
#include "txRtfHandler.h"
txResultTreeFragment::txResultTreeFragment(txResultBuffer* aBuffer)
: mBuffer(aBuffer)
txResultTreeFragment::txResultTreeFragment(nsAutoPtr<txResultBuffer>& aBuffer)
: txAExprResult(nsnull), mBuffer(aBuffer)
{
}
@ -48,11 +48,6 @@ txResultTreeFragment::~txResultTreeFragment()
{
}
ExprResult* txResultTreeFragment::clone()
{
return new txResultTreeFragment(mBuffer);
}
short txResultTreeFragment::getResultType()
{
return RESULT_TREE_FRAGMENT;
@ -103,9 +98,15 @@ txRtfHandler::~txRtfHandler()
{
}
txResultTreeFragment* txRtfHandler::createRTF()
nsresult
txRtfHandler::getAsRTF(txAExprResult** aResult)
{
return new txResultTreeFragment(mBuffer);
*aResult = new txResultTreeFragment(mBuffer);
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aResult);
return NS_OK;
}
void txRtfHandler::endDocument()

Просмотреть файл

@ -43,10 +43,10 @@
#include "txBufferingHandler.h"
#include "ExprResult.h"
class txResultTreeFragment : public ExprResult
class txResultTreeFragment : public txAExprResult
{
public:
txResultTreeFragment(txResultBuffer* aBuffer);
txResultTreeFragment(nsAutoPtr<txResultBuffer>& aBuffer);
~txResultTreeFragment();
TX_DECL_EXPRRESULT
@ -54,7 +54,7 @@ public:
nsresult flushToHandler(txAXMLEventHandler* aHandler);
private:
nsRefPtr<txResultBuffer> mBuffer;
nsAutoPtr<txResultBuffer> mBuffer;
};
class txRtfHandler : public txBufferingHandler
@ -63,7 +63,7 @@ public:
txRtfHandler();
virtual ~txRtfHandler();
txResultTreeFragment* createRTF();
nsresult getAsRTF(txAExprResult** aResult);
void endDocument();
void startDocument();

Просмотреть файл

@ -240,7 +240,7 @@ protected:
class txIGlobalParameter : public TxObject
{
public:
virtual nsresult getValue(ExprResult** aValue) = 0;
virtual nsresult getValue(txAExprResult** aValue) = 0;
};

Просмотреть файл

@ -1131,7 +1131,7 @@ txFnEndTopVariable(txStylesheetCompilerState& aState)
// No children were found.
NS_ASSERTION(!var->mValue,
"There shouldn't be a select-expression here");
var->mValue = new StringExpr(NS_LITERAL_STRING(""));
var->mValue = new txLiteralExpr(NS_LITERAL_STRING(""));
NS_ENSURE_TRUE(var->mValue, NS_ERROR_OUT_OF_MEMORY);
}
else if (!var->mValue) {
@ -2126,7 +2126,7 @@ txFnEndParam(txStylesheetCompilerState& aState)
// No children were found.
NS_ASSERTION(!var->mValue,
"There shouldn't be a select-expression here");
var->mValue = new StringExpr(NS_LITERAL_STRING(""));
var->mValue = new txLiteralExpr(NS_LITERAL_STRING(""));
NS_ENSURE_TRUE(var->mValue, NS_ERROR_OUT_OF_MEMORY);
}
@ -2404,7 +2404,7 @@ txFnEndVariable(txStylesheetCompilerState& aState)
// No children were found.
NS_ASSERTION(!var->mValue,
"There shouldn't be a select-expression here");
var->mValue = new StringExpr(NS_LITERAL_STRING(""));
var->mValue = new txLiteralExpr(NS_LITERAL_STRING(""));
NS_ENSURE_TRUE(var->mValue, NS_ERROR_OUT_OF_MEMORY);
}
@ -2567,7 +2567,7 @@ txFnEndWithParam(txStylesheetCompilerState& aState)
// No children were found.
NS_ASSERTION(!var->mValue,
"There shouldn't be a select-expression here");
var->mValue = new StringExpr(NS_LITERAL_STRING(""));
var->mValue = new txLiteralExpr(NS_LITERAL_STRING(""));
NS_ENSURE_TRUE(var->mValue, NS_ERROR_OUT_OF_MEMORY);
}

Просмотреть файл

@ -27,43 +27,46 @@ SystemPropertyFunctionCall::SystemPropertyFunctionCall(txNamespaceMap* aMappings
* @return the result of the evaluation
* @see FunctionCall.h
**/
ExprResult* SystemPropertyFunctionCall::evaluate(txIEvalContext* aContext)
nsresult
SystemPropertyFunctionCall::evaluate(txIEvalContext* aContext,
txAExprResult** aResult)
{
ExprResult* result = nsnull;
*aResult = nsnull;
if (requireParams(1, 1, aContext)) {
txListIterator iter(&params);
Expr* param = (Expr*)iter.next();
ExprResult* exprResult = param->evaluate(aContext);
if (exprResult->getResultType() == ExprResult::STRING) {
nsAutoString property;
exprResult->stringValue(property);
txExpandedName qname;
nsresult rv = qname.init(property, mMappings, MB_TRUE);
if (NS_SUCCEEDED(rv) &&
qname.mNamespaceID == kNameSpaceID_XSLT) {
if (qname.mLocalName == txXSLTAtoms::version) {
result = new NumberResult(1.0);
}
else if (qname.mLocalName == txXSLTAtoms::vendor) {
result = new StringResult(NS_LITERAL_STRING("Transformiix"));
}
else if (qname.mLocalName == txXSLTAtoms::vendorUrl) {
result = new StringResult(NS_LITERAL_STRING("http://www.mozilla.org/projects/xslt/"));
}
}
}
else {
NS_NAMED_LITERAL_STRING(err, "Invalid argument passed to system-property(), expecting String");
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
result = new StringResult(err);
}
if (!requireParams(1, 1, aContext)) {
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
}
if (!result) {
result = new StringResult();
txListIterator iter(&params);
Expr* param = (Expr*)iter.next();
nsRefPtr<txAExprResult> exprResult;
nsresult rv = param->evaluate(aContext, getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString property;
exprResult->stringValue(property);
txExpandedName qname;
rv = qname.init(property, mMappings, MB_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
if (qname.mNamespaceID == kNameSpaceID_XSLT) {
if (qname.mLocalName == txXSLTAtoms::version) {
return aContext->recycler()->getNumberResult(1.0, aResult);
}
if (qname.mLocalName == txXSLTAtoms::vendor) {
return aContext->recycler()->getStringResult(
NS_LITERAL_STRING("Transformiix"), aResult);
}
if (qname.mLocalName == txXSLTAtoms::vendorUrl) {
return aContext->recycler()->getStringResult(
NS_LITERAL_STRING("http://www.mozilla.org/projects/xslt/"),
aResult);
}
}
return result;
aContext->recycler()->getEmptyStringResult(aResult);
return NS_OK;
}
nsresult SystemPropertyFunctionCall::getNameAtom(nsIAtom** aAtom)

Просмотреть файл

@ -47,59 +47,60 @@
class txVariableMap {
public:
txVariableMap();
~txVariableMap();
nsresult bindVariable(const txExpandedName& aName,
ExprResult* aValue, MBool aOwned);
nsresult bindVariable(const txExpandedName& aName, txAExprResult* aValue);
ExprResult* getVariable(const txExpandedName& aName);
void getVariable(const txExpandedName& aName, txAExprResult** aResult);
void removeVariable(const txExpandedName& aName);
private:
// Map with owned variables
txExpandedNameMap mOwnedVariables;
// Map with non-owned variables
txExpandedNameMap mNonOwnedVariables;
txExpandedNameMap mMap;
};
inline txVariableMap::txVariableMap()
: mOwnedVariables(MB_TRUE),
mNonOwnedVariables(MB_FALSE)
inline
txVariableMap::txVariableMap()
: mMap(MB_FALSE)
{
}
inline nsresult txVariableMap::bindVariable(const txExpandedName& aName,
ExprResult* aValue, MBool aOwned)
inline
txVariableMap::~txVariableMap()
{
nsresult rv = NS_ERROR_FAILURE;
if (aOwned) {
if (!mNonOwnedVariables.get(aName)) {
rv = mOwnedVariables.add(aName, aValue);
}
txExpandedNameMap::iterator iter(mMap);
while (iter.next()) {
txAExprResult* res = NS_STATIC_CAST(txAExprResult*, iter.value());
NS_RELEASE(res);
}
else {
if (!mOwnedVariables.get(aName)) {
rv = mNonOwnedVariables.add(aName, aValue);
}
}
inline nsresult
txVariableMap::bindVariable(const txExpandedName& aName, txAExprResult* aValue)
{
NS_ASSERTION(aValue, "can't add null-variables to a txVariableMap");
nsresult rv = mMap.add(aName, aValue);
if (NS_SUCCEEDED(rv)) {
NS_ADDREF(aValue);
}
return rv;
}
inline ExprResult* txVariableMap::getVariable(const txExpandedName& aName)
inline void
txVariableMap::getVariable(const txExpandedName& aName, txAExprResult** aResult)
{
ExprResult* var = (ExprResult*)mOwnedVariables.get(aName);
if (!var) {
var = (ExprResult*)mNonOwnedVariables.get(aName);
*aResult = NS_STATIC_CAST(txAExprResult*, mMap.get(aName));
if (*aResult) {
NS_ADDREF(*aResult);
}
return var;
}
inline void txVariableMap::removeVariable(const txExpandedName& aName)
inline void
txVariableMap::removeVariable(const txExpandedName& aName)
{
mOwnedVariables.remove(aName);
mNonOwnedVariables.remove(aName);
txAExprResult* var = NS_STATIC_CAST(txAExprResult*, mMap.remove(aName));
NS_IF_RELEASE(var);
}
#endif //TRANSFRMX_VARIABLEMAP_H

Просмотреть файл

@ -107,7 +107,7 @@ nsresult txResultStringComparator::init(const nsAFlatString& aLanguage)
}
#endif
TxObject* txResultStringComparator::createSortableValue(ExprResult* aExprRes)
TxObject* txResultStringComparator::createSortableValue(txAExprResult* aExprRes)
{
StringValue* val = new StringValue;
@ -279,7 +279,7 @@ txResultNumberComparator::~txResultNumberComparator()
{
}
TxObject* txResultNumberComparator::createSortableValue(ExprResult* aExprRes)
TxObject* txResultNumberComparator::createSortableValue(txAExprResult* aExprRes)
{
NumberValue* numval = new NumberValue;
if (numval)

Просмотреть файл

@ -48,7 +48,7 @@
#include "nsString.h"
#endif
class ExprResult;
class txAExprResult;
/*
* Result comparators
@ -69,7 +69,7 @@ public:
/*
* Create a sortable value.
*/
virtual TxObject* createSortableValue(ExprResult* exprRes) = 0;
virtual TxObject* createSortableValue(txAExprResult* exprRes) = 0;
};
/*
@ -83,7 +83,7 @@ public:
virtual ~txResultStringComparator();
int compareValues(TxObject* aVal1, TxObject* aVal2);
TxObject* createSortableValue(ExprResult* aExprRes);
TxObject* createSortableValue(txAExprResult* aExprRes);
private:
#ifndef TX_EXE
nsCOMPtr<nsICollation> mCollation;
@ -121,7 +121,7 @@ public:
virtual ~txResultNumberComparator();
int compareValues(TxObject* aVal1, TxObject* aVal2);
TxObject* createSortableValue(ExprResult* aExprRes);
TxObject* createSortableValue(txAExprResult* aExprRes);
private:
int mAscending;

Просмотреть файл

@ -114,14 +114,15 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern,
nsAString& aValueString)
{
aValueString.Truncate();
nsresult rv = NS_OK;
// If the value attribute exists then use that
if (aValueExpr) {
ExprResult* result = aValueExpr->evaluate(aContext);
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> result;
rv = aValueExpr->evaluate(aContext, getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
double value = result->numberValue();
delete result;
if (Double::isInfinite(value) || Double::isNaN(value) ||
value < 0.5) {
@ -319,12 +320,12 @@ txXSLTNumber::getCounters(Expr* aGroupSize, Expr* aGroupSeparator,
nsAutoString groupSeparator;
PRInt32 groupSize = 0;
if (aGroupSize && aGroupSeparator) {
ExprResult* sizeRes = aGroupSize->evaluate(aContext);
NS_ENSURE_TRUE(sizeRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> exprRes;
rv = aGroupSize->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString sizeStr;
sizeRes->stringValue(sizeStr);
delete sizeRes;
exprRes->stringValue(sizeStr);
double size = Double::toDouble(sizeStr);
groupSize = (PRInt32)size;
@ -332,20 +333,19 @@ txXSLTNumber::getCounters(Expr* aGroupSize, Expr* aGroupSeparator,
groupSize = 0;
}
ExprResult* sepRes = aGroupSeparator->evaluate(aContext);
NS_ENSURE_TRUE(sepRes, NS_ERROR_FAILURE);
rv = aGroupSeparator->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
sepRes->stringValue(groupSeparator);
delete sepRes;
exprRes->stringValue(groupSeparator);
}
nsAutoString format;
if (aFormat) {
ExprResult* formatRes = aFormat->evaluate(aContext);
NS_ENSURE_TRUE(formatRes, NS_ERROR_FAILURE);
nsRefPtr<txAExprResult> formatRes;
rv = aFormat->evaluate(aContext, getter_AddRefs(formatRes));
NS_ENSURE_SUCCESS(rv, rv);
formatRes->stringValue(format);
delete formatRes;
}
PRUint32 formatLen = format.Length();
PRUint32 formatPos = 0;

Просмотреть файл

@ -418,12 +418,12 @@ MBool txKeyPattern::matches(Node* aNode, txIMatchContext* aContext)
contextDoc = (Document*)aNode;
else
contextDoc = aNode->getOwnerDocument();
const NodeSet* nodes = 0;
nsresult rv = es->getKeyNodes(mName, contextDoc, mValue, PR_TRUE, &nodes);
if (NS_FAILED(rv) || !nodes)
return MB_FALSE;
MBool isTrue = nodes->contains(aNode);
return isTrue;
nsRefPtr<NodeSet> nodes;
nsresult rv = es->getKeyNodes(mName, contextDoc, mValue, PR_TRUE,
getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, PR_FALSE);
return nodes->contains(aNode);
}
double txKeyPattern::getDefaultPriority()
@ -498,7 +498,10 @@ MBool txStepPattern::matches(Node* aNode, txIMatchContext* aContext)
*/
// Create the context node set for evaluating the predicates
NodeSet nodes;
nsRefPtr<NodeSet> nodes;
nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
Node* parent = aNode->getXPathParent();
if (mIsAttr) {
NamedNodeMap* atts = parent->getAttributes();
@ -507,7 +510,7 @@ MBool txStepPattern::matches(Node* aNode, txIMatchContext* aContext)
for (i = 0; i < atts->getLength(); i++) {
Node* attr = atts->item(i);
if (mNodeTest->matches(attr, aContext))
nodes.append(attr);
nodes->append(attr);
}
}
}
@ -515,33 +518,36 @@ MBool txStepPattern::matches(Node* aNode, txIMatchContext* aContext)
Node* tmpNode = parent->getFirstChild();
while (tmpNode) {
if (mNodeTest->matches(tmpNode, aContext))
nodes.append(tmpNode);
nodes->append(tmpNode);
tmpNode = tmpNode->getNextSibling();
}
}
txListIterator iter(&predicates);
Expr* predicate = (Expr*)iter.next();
NodeSet newNodes;
nsRefPtr<NodeSet> newNodes;
rv = aContext->recycler()->getNodeSet(getter_AddRefs(newNodes));
NS_ENSURE_SUCCESS(rv, rv);
while (iter.hasNext()) {
newNodes.clear();
newNodes->clear();
MBool contextIsInPredicate = MB_FALSE;
txNodeSetContext predContext(&nodes, aContext);
txNodeSetContext predContext(nodes, aContext);
while (predContext.hasNext()) {
predContext.next();
ExprResult* exprResult = predicate->evaluate(&predContext);
if (!exprResult)
break;
nsRefPtr<txAExprResult> exprResult;
rv = predicate->evaluate(&predContext, getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, PR_FALSE);
switch(exprResult->getResultType()) {
case ExprResult::NUMBER :
case txAExprResult::NUMBER:
// handle default, [position() == numberValue()]
if ((double)predContext.position() ==
exprResult->numberValue()) {
Node* tmp = predContext.getContextNode();
if (tmp == aNode)
contextIsInPredicate = MB_TRUE;
newNodes.append(tmp);
newNodes->append(tmp);
}
break;
default:
@ -549,25 +555,25 @@ MBool txStepPattern::matches(Node* aNode, txIMatchContext* aContext)
Node* tmp = predContext.getContextNode();
if (tmp == aNode)
contextIsInPredicate = MB_TRUE;
newNodes.append(tmp);
newNodes->append(tmp);
}
break;
}
delete exprResult;
}
// Move new NodeSet to the current one
nodes.clear();
nodes.append(&newNodes);
nodes->clear();
nodes->append(newNodes);
if (!contextIsInPredicate) {
return MB_FALSE;
}
predicate = (Expr*)iter.next();
}
txForwardContext evalContext(aContext, aNode, &nodes);
ExprResult* exprResult = predicate->evaluate(&evalContext);
if (!exprResult)
return MB_FALSE;
if (exprResult->getResultType() == ExprResult::NUMBER)
txForwardContext evalContext(aContext, aNode, nodes);
nsRefPtr<txAExprResult> exprResult;
rv = predicate->evaluate(&evalContext, getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, PR_FALSE);
if (exprResult->getResultType() == txAExprResult::NUMBER)
// handle default, [position() == numberValue()]
return ((double)evalContext.position() == exprResult->numberValue());

Просмотреть файл

@ -42,6 +42,7 @@
#include "TxLog.h"
#include "txStylesheetCompileHandlers.h"
#include "txExecutionState.h"
#include "ExprResult.h"
#ifdef TX_EXE
#include "txHTMLOutput.h"
#endif