From 3f4f453c70747ee9817778831035cccc8d94d19b Mon Sep 17 00:00:00 2001 From: "sicking%bigfoot.com" Date: Mon, 28 Jan 2002 14:46:39 +0000 Subject: [PATCH] Cleanup BooleanFunctionCall and StringFunctionCall, fixes bugs in lang(), substring() and a few more. b=104758 r=Pike sr=jag git-svn-id: svn://10.0.0.236/trunk@113036 18797224-902f-48f8-a5cc-f745e15eee43 --- .../source/xpath/BooleanFunctionCall.cpp | 121 ++++-- .../transformiix/source/xpath/Expr.h | 30 +- .../source/xpath/FunctionCall.cpp | 66 ++- .../transformiix/source/xpath/FunctionLib.h | 48 ++- .../source/xpath/NumberFunctionCall.cpp | 25 +- .../source/xpath/StringFunctionCall.cpp | 404 +++++++++--------- .../functions/txFormatNumberFunctionCall.cpp | 6 +- 7 files changed, 380 insertions(+), 320 deletions(-) diff --git a/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp index 77f8a3d64be..8ad9a3484bf 100644 --- a/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp @@ -1,4 +1,5 @@ -/* +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * * 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 @@ -32,9 +33,10 @@ /** * Creates a default BooleanFunctionCall, which always evaluates to False **/ -BooleanFunctionCall::BooleanFunctionCall(short type) : FunctionCall() +BooleanFunctionCall::BooleanFunctionCall(BooleanFunctions aType) + : mType(aType) { - switch ( type ) { + switch (aType) { case TX_BOOLEAN : name = XPathNames::BOOLEAN_FN; break; @@ -51,7 +53,6 @@ BooleanFunctionCall::BooleanFunctionCall(short type) : FunctionCall() name = XPathNames::FALSE_FN; break; } - this->type = type; } //-- BooleanFunctionCall /** @@ -61,49 +62,77 @@ BooleanFunctionCall::BooleanFunctionCall(short type) : FunctionCall() * for evaluation * @return the result of the evaluation **/ -ExprResult* BooleanFunctionCall::evaluate(Node* context, ContextState* cs) { +ExprResult* BooleanFunctionCall::evaluate(Node* aContext, ContextState* aCs) +{ + ListIterator iter(¶ms); - MBool result = MB_FALSE; - ListIterator* iter = params.iterator(); - Expr* param = 0; - String err; + switch (mType) { + case TX_BOOLEAN: + { + if (!requireParams(1, 1, aCs)) + return new StringResult("error"); - - switch ( type ) { - case TX_BOOLEAN : - if ( requireParams(1,1,cs) ) { - param = (Expr*)iter->next(); - ExprResult* exprResult = param->evaluate(context, cs); - result = exprResult->booleanValue(); - delete exprResult; - } - break; + return new BooleanResult(evaluateToBoolean((Expr*)iter.next(), + aContext, + aCs)); + } case TX_LANG: - if ( requireParams(1,1,cs) ) { - String arg1, lang; - evaluateToString((Expr*)iter->next(),context, cs, arg1); - ((Element*)context)->getAttr(txXMLAtoms::lang, - kNameSpaceID_XML, lang); - arg1.toUpperCase(); // case-insensitive comparison - lang.toUpperCase(); - result = (MBool)(lang.indexOf(arg1) == 0); - } - break; - case TX_NOT : - if ( requireParams(1,1,cs) ) { - param = (Expr*)iter->next(); - ExprResult* exprResult = param->evaluate(context, cs); - result = (MBool)(!exprResult->booleanValue()); - delete exprResult; - } - break; - case TX_TRUE : - result = MB_TRUE; - break; - default: - break; - } - delete iter; - return new BooleanResult(result); -} //-- evaluate + { + if (!requireParams(1, 1, aCs)) + return new StringResult("error"); + + String lang; + Node* node = aContext; + while (node) { + if (node->getNodeType() == Node::ELEMENT_NODE) { + Element* elem = (Element*)node; + if (elem->getAttr(txXMLAtoms::lang, + kNameSpaceID_XML, lang)) + break; + } + node = node->getParentNode(); + } + + MBool result = MB_FALSE; + if (node) { + String arg; + evaluateToString((Expr*)iter.next(),aContext, aCs, arg); + arg.toUpperCase(); // case-insensitive comparison + lang.toUpperCase(); + result = lang.indexOf(arg) == 0 && + (lang.length() == arg.length() || + lang.charAt(arg.length()) == '-'); + } + + return new BooleanResult(result); + } + case TX_NOT: + { + if (!requireParams(1, 1, aCs)) + return new StringResult("error"); + + return new BooleanResult(!evaluateToBoolean((Expr*)iter.next(), + aContext, + aCs)); + } + case TX_TRUE: + { + if (!requireParams(0, 0, aCs)) + return new StringResult("error"); + + return new BooleanResult(MB_TRUE); + } + case TX_FALSE: + { + if (!requireParams(0, 0, aCs)) + return new StringResult("error"); + + return new BooleanResult(MB_FALSE); + } + } + + String err("Internal error"); + aCs->recieveError(err); + return new StringResult("error"); +} diff --git a/mozilla/extensions/transformiix/source/xpath/Expr.h b/mozilla/extensions/transformiix/source/xpath/Expr.h index 0a3001064fa..9dcb61a1b35 100644 --- a/mozilla/extensions/transformiix/source/xpath/Expr.h +++ b/mozilla/extensions/transformiix/source/xpath/Expr.h @@ -1,4 +1,5 @@ -/* +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * * 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 @@ -188,20 +189,25 @@ protected: FunctionCall(); FunctionCall(const String& name); - /** - * Evaluates the given Expression and converts it's result to a String. + /* + * Evaluates the given Expression and converts its result to a String. * The value is appended to the given destination String - **/ - void evaluateToString - (Expr* expr, Node* context, ContextState* cs, String& dest); - - /** - * Evaluates the given Expression and converts it's result to a number. - **/ - double evaluateToNumber(Expr* expr, Node* context, ContextState* cs); + */ + void evaluateToString(Expr* aExpr, Node* aContext, + ContextState* aCs, String& aDest); /* - * Evaluates the given Expression and converts it's result to a NodeSet. + * Evaluates the given Expression and converts its result to a number. + */ + double evaluateToNumber(Expr* aExpr, Node* aContext, ContextState* aCs); + + /* + * Evaluates the given Expression and converts its result to a boolean. + */ + MBool evaluateToBoolean(Expr* aExpr, Node* aContext, ContextState* aCs); + + /* + * Evaluates the given Expression and converts its result to a NodeSet. * If the result is not a NodeSet NULL is returned. */ NodeSet* evaluateToNodeSet(Expr* aExpr, Node* aContext, ContextState* aCs); diff --git a/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp index 9bd748fb1e1..c2b6bbafdff 100644 --- a/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp @@ -110,34 +110,57 @@ MBool FunctionCall::matches(Node* node, Node* context, ContextState* cs) return result; } //-- matches -/** - * Evaluates the given Expression and converts it's result to a String. +/* + * Evaluates the given Expression and converts its result to a String. * The value is appended to the given destination String -**/ -void FunctionCall::evaluateToString(Expr* expr, Node* context, - ContextState* cs, String& dest) + */ +void FunctionCall::evaluateToString(Expr* aExpr, + Node* aContext, + ContextState* aCs, + String& aDest) { - if (!expr) + NS_ASSERTION(aExpr, "missing expression"); + ExprResult* exprResult = aExpr->evaluate(aContext, aCs); + if (!exprResult) return; - ExprResult* exprResult = expr->evaluate(context, cs); - exprResult->stringValue(dest); - delete exprResult; -} //-- evaluateToString -/** - * Evaluates the given Expression and converts it's result to a number. -**/ -double FunctionCall::evaluateToNumber(Expr* expr, Node* context, - ContextState* cs) + exprResult->stringValue(aDest); + delete exprResult; +} + +/* + * Evaluates the given Expression and converts its result to a number. + */ +double FunctionCall::evaluateToNumber(Expr* aExpr, + Node* aContext, + ContextState* aCs) { - double result = Double::NaN; - if (!expr) - return result; - ExprResult* exprResult = expr->evaluate(context, cs); - result = exprResult->numberValue(); + NS_ASSERTION(aExpr, "missing expression"); + ExprResult* exprResult = aExpr->evaluate(aContext, aCs); + if (!exprResult) + return Double::NaN; + + double result = exprResult->numberValue(); delete exprResult; return result; -} //-- evaluateToNumber +} + +/* + * Evaluates the given Expression and converts its result to a boolean. + */ +MBool FunctionCall::evaluateToBoolean(Expr* aExpr, + Node* aContext, + ContextState* aCs) +{ + NS_ASSERTION(aExpr, "missing expression"); + ExprResult* exprResult = aExpr->evaluate(aContext, aCs); + if (!exprResult) + return MB_FALSE; + + MBool result = exprResult->booleanValue(); + delete exprResult; + return result; +} /* * Evaluates the given Expression and converts its result to a NodeSet. @@ -148,7 +171,6 @@ NodeSet* FunctionCall::evaluateToNodeSet(Expr* aExpr, ContextState* aCs) { NS_ASSERTION(aExpr, "Missing expression to evaluate"); - ExprResult* exprResult = aExpr->evaluate(aContext, aCs); if (!exprResult) return 0; diff --git a/mozilla/extensions/transformiix/source/xpath/FunctionLib.h b/mozilla/extensions/transformiix/source/xpath/FunctionLib.h index 85d4da107c2..64611b82d45 100644 --- a/mozilla/extensions/transformiix/source/xpath/FunctionLib.h +++ b/mozilla/extensions/transformiix/source/xpath/FunctionLib.h @@ -112,12 +112,18 @@ class BooleanFunctionCall : public FunctionCall { public: - enum booleanFunctions { TX_BOOLEAN = 1, TX_FALSE, TX_LANG, TX_NOT, TX_TRUE }; + enum BooleanFunctions { + TX_BOOLEAN, // boolean() + TX_FALSE, // false() + TX_LANG, // lang() + TX_NOT, // not() + TX_TRUE // true() + }; /** * Creates a BooleanFunctionCall of the given type **/ - BooleanFunctionCall(short type); + BooleanFunctionCall(BooleanFunctions aType); /** * Evaluates this Expr based on the given context node and processor state @@ -126,10 +132,10 @@ public: * for evaluation * @return the result of the evaluation **/ - virtual ExprResult* evaluate(Node* context, ContextState* cs); + ExprResult* evaluate(Node* aContext, ContextState* aCs); private: - short type; + BooleanFunctions mType; }; //-- BooleanFunctionCall /** @@ -271,7 +277,7 @@ public: * for evaluation * @return the result of the evaluation */ - virtual ExprResult* evaluate(Node* context, ContextState* cs); + ExprResult* evaluate(Node* aContext, ContextState* aCs); private: NodeSetFunctions mType; @@ -285,23 +291,23 @@ class StringFunctionCall : public FunctionCall { public: - enum stringFunctions { - CONCAT = 1, //-- concat() - CONTAINS, //-- contains() - NORMALIZE_SPACE, //-- normalize-space() - STARTS_WITH, //-- starts-with() - STRING, //-- string() - STRING_LENGTH, //-- string-length() - SUBSTRING, //-- substring() - SUBSTRING_AFTER, //-- substring-after() - SUBSTRING_BEFORE, //-- substring-before() - TRANSLATE //-- translate() + enum StringFunctions { + CONCAT, // concat() + CONTAINS, // contains() + NORMALIZE_SPACE, // normalize-space() + STARTS_WITH, // starts-with() + STRING, // string() + STRING_LENGTH, // string-length() + SUBSTRING, // substring() + SUBSTRING_AFTER, // substring-after() + SUBSTRING_BEFORE, // substring-before() + TRANSLATE // translate() }; /** * Creates a String function of the given type **/ - StringFunctionCall(short type); + StringFunctionCall(StringFunctions aType); /** * Evaluates this Expr based on the given context node and processor state @@ -310,10 +316,10 @@ public: * for evaluation * @return the result of the evaluation **/ - virtual ExprResult* evaluate(Node* context, ContextState* cs); + ExprResult* evaluate(Node* aContext, ContextState* aCs); private: - short type; + StringFunctions mType; }; //-- StringFunctionCall @@ -335,7 +341,7 @@ public: /* * Creates a Number function of the given type */ - NumberFunctionCall(NumberFunctions type); + NumberFunctionCall(NumberFunctions aType); /* * Evaluates this Expr based on the given context node and processor state @@ -344,7 +350,7 @@ public: * for evaluation * @return the result of the evaluation */ - virtual ExprResult* evaluate(Node* context, ContextState* cs); + ExprResult* evaluate(Node* aContext, ContextState* aCs); private: NumberFunctions mType; diff --git a/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp index 3106cc4e43d..34274f74cf8 100644 --- a/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp @@ -68,22 +68,23 @@ NumberFunctionCall::NumberFunctionCall(NumberFunctions aType) { * for evaluation * @return the result of the evaluation */ -ExprResult* NumberFunctionCall::evaluate(Node* context, ContextState* cs) { +ExprResult* NumberFunctionCall::evaluate(Node* aContext, ContextState* aCs) +{ ListIterator iter(¶ms); if (mType == NUMBER) { - if (!requireParams(0, 1, cs)) + if (!requireParams(0, 1, aCs)) return new StringResult("error"); } else { - if (!requireParams(1, 1, cs)) + if (!requireParams(1, 1, aCs)) return new StringResult("error"); } switch (mType) { case CEILING: { - double dbl = evaluateToNumber((Expr*)iter.next(), context, cs); + double dbl = evaluateToNumber((Expr*)iter.next(), aContext, aCs); if (Double::isNaN(dbl) || Double::isInfinite(dbl)) return new NumberResult(dbl); @@ -94,7 +95,7 @@ ExprResult* NumberFunctionCall::evaluate(Node* context, ContextState* cs) { } case FLOOR: { - double dbl = evaluateToNumber((Expr*)iter.next(), context, cs); + double dbl = evaluateToNumber((Expr*)iter.next(), aContext, aCs); if (Double::isNaN(dbl) || Double::isInfinite(dbl) || (dbl == 0 && Double::isNeg(dbl))) @@ -104,7 +105,7 @@ ExprResult* NumberFunctionCall::evaluate(Node* context, ContextState* cs) { } case ROUND: { - double dbl = evaluateToNumber((Expr*)iter.next(), context, cs); + double dbl = evaluateToNumber((Expr*)iter.next(), aContext, aCs); if (Double::isNaN(dbl) || Double::isInfinite(dbl)) return new NumberResult(dbl); @@ -116,7 +117,7 @@ ExprResult* NumberFunctionCall::evaluate(Node* context, ContextState* cs) { case SUM: { NodeSet* nodes; - nodes = evaluateToNodeSet((Expr*)iter.next(), context, cs); + nodes = evaluateToNodeSet((Expr*)iter.next(), aContext, aCs); if (!nodes) return new StringResult("error"); @@ -134,14 +135,18 @@ ExprResult* NumberFunctionCall::evaluate(Node* context, ContextState* cs) { } case NUMBER: { - if (iter.hasNext()) + if (iter.hasNext()) { return new NumberResult( - evaluateToNumber((Expr*)iter.next(), context, cs)); + evaluateToNumber((Expr*)iter.next(), aContext, aCs)); + } String resultStr; - XMLDOMUtils::getNodeValue(context, resultStr); + XMLDOMUtils::getNodeValue(aContext, resultStr); return new NumberResult(Double::toDouble(resultStr)); } } + + String err("Internal error"); + aCs->recieveError(err); return new StringResult("error"); } diff --git a/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp index ae8f1955781..74dd2cc363e 100644 --- a/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp @@ -1,4 +1,5 @@ -/* +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * * 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 @@ -29,16 +30,15 @@ **/ #include "FunctionLib.h" -#include "XMLUtils.h" #include "XMLDOMUtils.h" #include /** * Creates a StringFunctionCall of the given type **/ -StringFunctionCall::StringFunctionCall(short type) : FunctionCall() { - this->type = type; - switch ( type ) { +StringFunctionCall::StringFunctionCall(StringFunctions aType) : mType(aType) +{ + switch (aType) { case CONCAT: name = XPathNames::CONCAT_FN; break; @@ -67,7 +67,7 @@ StringFunctionCall::StringFunctionCall(short type) : FunctionCall() { name = XPathNames::STRING_FN; break; } -} //-- StringFunctionCall +} /** * Evaluates this Expr based on the given context node and processor state @@ -76,214 +76,202 @@ StringFunctionCall::StringFunctionCall(short type) : FunctionCall() { * for evaluation * @return the result of the evaluation **/ -ExprResult* StringFunctionCall::evaluate(Node* context, ContextState* cs) { - ListIterator* iter = params.iterator(); - PRInt32 argc = params.getLength(); - String err; - ExprResult* result = 0; - switch ( type ) { - case CONCAT : - if ( requireParams(2, cs) ) { - String resultStr; - while(iter->hasNext()) { - evaluateToString((Expr*)iter->next(),context, cs, resultStr); - } - result = new StringResult(resultStr); +ExprResult* StringFunctionCall::evaluate(Node* aContext, ContextState* aCs) +{ + ListIterator iter(¶ms); + switch (mType) { + case CONCAT: + { + if (!requireParams(2, aCs)) + return new StringResult("error"); + + String resultStr; + while (iter.hasNext()) { + evaluateToString((Expr*)iter.next(), aContext, aCs, resultStr); } - else result = new StringResult(""); - break; - case CONTAINS : - if ( requireParams(2, 2, cs) ) { - String arg1, arg2; - evaluateToString((Expr*)iter->next(),context, cs, arg1); - evaluateToString((Expr*)iter->next(),context, cs, arg2); - result = new BooleanResult((MBool)(arg1.indexOf(arg2) >= 0)); - } - else result = new BooleanResult(MB_FALSE); - break; + return new StringResult(resultStr); + } + case CONTAINS: + { + if (!requireParams(2, 2, aCs)) + return new StringResult("error"); + String arg1, arg2; + evaluateToString((Expr*)iter.next(), aContext, aCs, arg1); + evaluateToString((Expr*)iter.next(), aContext, aCs, arg2); + return new BooleanResult(arg1.indexOf(arg2) >= 0); + } case NORMALIZE_SPACE: - if ( requireParams(0, 1, cs) ) { - String resultStr; - if ( argc == 1) - evaluateToString((Expr*)iter->next(),context, cs, resultStr); - else - XMLDOMUtils::getNodeValue(context, resultStr); - // Leading & Trailing Whitespace - resultStr.trim(); - MBool hasSpace = MB_FALSE; - PRInt32 dest=0; - String normed(resultStr.length()); - UNICODE_CHAR current; - for (PRInt32 src=0; srcnext(),context, cs, arg1); - evaluateToString((Expr*)iter->next(),context, cs, arg2); - result = new BooleanResult((MBool)(arg1.indexOf(arg2) == 0)); - } - else result = new BooleanResult(MB_FALSE); - break; - case STRING_LENGTH: - if ( requireParams(0, 1, cs) ) { - String resultStr; - if ( argc == 1) { - evaluateToString((Expr*)iter->next(),context, cs, resultStr); - } - else XMLDOMUtils::getNodeValue(context, resultStr); - result = new NumberResult( (double) resultStr.length()); - } - else result = new NumberResult(0.0); - break; - case SUBSTRING: - if ( requireParams(2, 3, cs) ) { - String src; - evaluateToString((Expr*)iter->next(),context, cs, src); - double dbl = evaluateToNumber((Expr*)iter->next(), context, cs); + { + if (!requireParams(0, 1, aCs)) + return new StringResult("error"); - //-- check for NaN - if ( Double::isNaN(dbl)) { - result = new StringResult(""); - break; - } - - //-- check for -Infinity - MBool startsNegInf = (dbl==Double::NEGATIVE_INFINITY); - - PRInt32 startIdx = startsNegInf?0:(PRInt32)floor(dbl+.5); - PRInt32 endIdx = src.length()+1; - if ( argc == 3) { - dbl = evaluateToNumber((Expr*)iter->next(),context, cs); - if (startsNegInf) { - result = new StringResult(""); - break; - } - if (dbl == Double::POSITIVE_INFINITY) ; //already complete - else if ( Double::isNaN(dbl) || - dbl == Double::NEGATIVE_INFINITY || - dbl < 0 ) - endIdx = 0; - else endIdx = startIdx+(PRInt32)floor(dbl+.5); - } - String resultStr; - //-- strings are indexed starting at 1 for XSL - //-- adjust to a 0-based index - endIdx--; - if (startIdx<1){ - startIdx = 0; - } else { - startIdx--; - } - - src.subString(startIdx,endIdx,resultStr); - result = new StringResult(resultStr); - } - else result = new StringResult(""); - break; - - case SUBSTRING_AFTER: - if ( requireParams(2, 2, cs) ) { - String arg1, arg2; - evaluateToString((Expr*)iter->next(),context, cs, arg1); - evaluateToString((Expr*)iter->next(),context, cs, arg2); - PRInt32 idx = arg1.indexOf(arg2); - if ((idx >= 0)&&(idxnext(),context, cs, arg1); - evaluateToString((Expr*)iter->next(),context, cs, arg2); - PRInt32 idx = arg1.indexOf(arg2); - if ((idx >= 0)&&(idxnext(),context, cs, src); - - if (src.isEmpty()) { - result = new StringResult(""); - break; - } - - String oldChars, newChars; - evaluateToString((Expr*)iter->next(),context, cs, oldChars); - evaluateToString((Expr*)iter->next(),context, cs, newChars); - PRInt32 size = src.length(); - UNICODE_CHAR* chars = src.toUnicode(new UNICODE_CHAR[size]); - src.clear(); - PRInt32 i; - for (i = 0; i < size; i++) { - PRInt32 idx = oldChars.indexOf(chars[i]); - if (idx >= 0) { - if (idx < newChars.length()) - src.append(newChars.charAt(idx)); - } - else { - src.append(chars[i]); - } - } - delete chars; - result = new StringResult(src); - } + String resultStr; + if (iter.hasNext()) + evaluateToString((Expr*)iter.next(), aContext, aCs, resultStr); else - result = new StringResult(""); - break; + XMLDOMUtils::getNodeValue(aContext, resultStr); - default : //-- string( object? ) - if ( requireParams(0, 1, cs) ) { - String resultStr; - if (iter->hasNext()) { - evaluateToString((Expr*)iter->next(),context, cs, resultStr); + MBool addSpace = MB_FALSE; + MBool first = MB_TRUE; + String normed(resultStr.length()); + UNICODE_CHAR c; + PRInt32 src; + for (src = 0; src < resultStr.length(); src++) { + c = resultStr.charAt(src); + if (c == ' ' || c == '\n' || + c == '\t' || c == '\r') { + addSpace = MB_TRUE; } else { - XMLDOMUtils::getNodeValue(context, resultStr); - if ( cs->isStripSpaceAllowed(context) && - XMLUtils::shouldStripTextnode(resultStr)) - resultStr = ""; - } - result = new StringResult(resultStr); - } - else result = new StringResult(""); - break; - } - delete iter; - return result; -} //-- evaluate + if (addSpace && !first) + normed.append(' '); + normed.append(c); + addSpace = MB_FALSE; + first = MB_FALSE; + } + } + return new StringResult(normed); + } + case STARTS_WITH: + { + if (!requireParams(2, 2, aCs)) + return new StringResult("error"); + + String arg1, arg2; + evaluateToString((Expr*)iter.next(), aContext, aCs, arg1); + evaluateToString((Expr*)iter.next(), aContext, aCs, arg2); + return new BooleanResult(arg1.indexOf(arg2) == 0); + } + case STRING_LENGTH: + { + if (!requireParams(0, 1, aCs)) + return new StringResult("error"); + + String resultStr; + if (iter.hasNext()) + evaluateToString((Expr*)iter.next(), aContext, aCs, resultStr); + else + XMLDOMUtils::getNodeValue(aContext, resultStr); + return new NumberResult(resultStr.length()); + } + case SUBSTRING: + { + if (!requireParams(2, 3, aCs)) + return new StringResult("error"); + + String src; + double start, end; + evaluateToString((Expr*)iter.next(), aContext, aCs, src); + start = evaluateToNumber((Expr*)iter.next(), aContext, aCs); + + // check for NaN or +/-Inf + if (Double::isNaN(start) || + Double::isInfinite(start) || + start + 0.5 >= src.length()) + return new StringResult(); + + start = floor(start + 0.5) - 1; + if (iter.hasNext()) { + end = start + evaluateToNumber((Expr*)iter.next(), + aContext, + aCs); + if (Double::isNaN(end) || end < 0) + return new StringResult(); + + if (end > src.length()) + end = src.length(); + else + end = floor(end + 0.5); + } + else { + end = src.length(); + } + + if (start < 0) + start = 0; + + if (start > end) + return new StringResult(); + + String resultStr; + src.subString((PRInt32)start, (PRInt32)end, resultStr); + return new StringResult(resultStr); + } + case SUBSTRING_AFTER: + { + if (!requireParams(2, 2, aCs)) + return new StringResult("error"); + + String arg1, arg2; + evaluateToString((Expr*)iter.next(), aContext, aCs, arg1); + evaluateToString((Expr*)iter.next(), aContext, aCs, arg2); + PRInt32 idx = arg1.indexOf(arg2); + if (idx >= 0) { + PRInt32 len = arg2.length(); + arg1.subString(idx + len, arg2); + return new StringResult(arg2); + } + return new StringResult(); + } + case SUBSTRING_BEFORE: + { + if (!requireParams(2, 2, aCs)) + return new StringResult("error"); + + String arg1, arg2; + evaluateToString((Expr*)iter.next(), aContext, aCs, arg1); + evaluateToString((Expr*)iter.next(), aContext, aCs, arg2); + PRInt32 idx = arg1.indexOf(arg2); + if (idx >= 0) { + arg2.clear(); + arg1.subString(0, idx, arg2); + return new StringResult(arg2); + } + return new StringResult(); + } + case TRANSLATE: + { + if (!requireParams(3, 3, aCs)) + return new StringResult("error"); + + String src; + evaluateToString((Expr*)iter.next(), aContext, aCs, src); + if (src.isEmpty()) + return new StringResult(); + + String oldChars, newChars, dest; + evaluateToString((Expr*)iter.next(), aContext, aCs, oldChars); + evaluateToString((Expr*)iter.next(), aContext, aCs, newChars); + PRInt32 i; + for (i = 0; i < src.length(); i++) { + PRInt32 idx = oldChars.indexOf(src.charAt(i)); + if (idx >= 0) { + if (idx < newChars.length()) + dest.append(newChars.charAt(idx)); + } + else { + dest.append(src.charAt(i)); + } + } + return new StringResult(dest); + } + case STRING: + { + if (!requireParams(0, 1, aCs)) + return new StringResult("error"); + + String resultStr; + if (iter.hasNext()) + evaluateToString((Expr*)iter.next(), aContext, aCs, resultStr); + else + XMLDOMUtils::getNodeValue(aContext, resultStr); + return new StringResult(resultStr); + } + } + + String err("Internal error"); + aCs->recieveError(err); + return new StringResult("error"); +} diff --git a/mozilla/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp index 0cc6695f5f1..f424fda39df 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp @@ -296,8 +296,12 @@ ExprResult* txFormatNumberFunctionCall::evaluate(Node* aContext, return new StringResult; } + int totalSize = minIntegerSize + maxFractionSize; + if (maxFractionSize > 0) + totalSize++; //to account for decimal point + char formatBuf[30]; - sprintf(formatBuf, "%%0%d.%df", minIntegerSize, maxFractionSize); + sprintf(formatBuf, "%%0%d.%df", totalSize, maxFractionSize); sprintf(buf, formatBuf, value);