summaryrefslogtreecommitdiffstats
path: root/dom/xslt/xpath/txCoreFunctionCall.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/xslt/xpath/txCoreFunctionCall.cpp')
-rw-r--r--dom/xslt/xpath/txCoreFunctionCall.cpp743
1 files changed, 743 insertions, 0 deletions
diff --git a/dom/xslt/xpath/txCoreFunctionCall.cpp b/dom/xslt/xpath/txCoreFunctionCall.cpp
new file mode 100644
index 000000000..82df8c8ee
--- /dev/null
+++ b/dom/xslt/xpath/txCoreFunctionCall.cpp
@@ -0,0 +1,743 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/FloatingPoint.h"
+
+#include "txExpr.h"
+#include "nsAutoPtr.h"
+#include "txNodeSet.h"
+#include "nsGkAtoms.h"
+#include "txIXPathContext.h"
+#include "nsWhitespaceTokenizer.h"
+#include "txXPathTreeWalker.h"
+#include <math.h>
+#include "txStringUtils.h"
+#include "txXMLUtils.h"
+
+using namespace mozilla;
+
+struct txCoreFunctionDescriptor
+{
+ int8_t mMinParams;
+ int8_t mMaxParams;
+ Expr::ResultType mReturnType;
+ nsIAtom** mName;
+};
+
+// This must be ordered in the same order as txCoreFunctionCall::eType.
+// If you change one, change the other.
+static const txCoreFunctionDescriptor descriptTable[] =
+{
+ { 1, 1, Expr::NUMBER_RESULT, &nsGkAtoms::count }, // COUNT
+ { 1, 1, Expr::NODESET_RESULT, &nsGkAtoms::id }, // ID
+ { 0, 0, Expr::NUMBER_RESULT, &nsGkAtoms::last }, // LAST
+ { 0, 1, Expr::STRING_RESULT, &nsGkAtoms::localName }, // LOCAL_NAME
+ { 0, 1, Expr::STRING_RESULT, &nsGkAtoms::namespaceUri }, // NAMESPACE_URI
+ { 0, 1, Expr::STRING_RESULT, &nsGkAtoms::name }, // NAME
+ { 0, 0, Expr::NUMBER_RESULT, &nsGkAtoms::position }, // POSITION
+
+ { 2, -1, Expr::STRING_RESULT, &nsGkAtoms::concat }, // CONCAT
+ { 2, 2, Expr::BOOLEAN_RESULT, &nsGkAtoms::contains }, // CONTAINS
+ { 0, 1, Expr::STRING_RESULT, &nsGkAtoms::normalizeSpace }, // NORMALIZE_SPACE
+ { 2, 2, Expr::BOOLEAN_RESULT, &nsGkAtoms::startsWith }, // STARTS_WITH
+ { 0, 1, Expr::STRING_RESULT, &nsGkAtoms::string }, // STRING
+ { 0, 1, Expr::NUMBER_RESULT, &nsGkAtoms::stringLength }, // STRING_LENGTH
+ { 2, 3, Expr::STRING_RESULT, &nsGkAtoms::substring }, // SUBSTRING
+ { 2, 2, Expr::STRING_RESULT, &nsGkAtoms::substringAfter }, // SUBSTRING_AFTER
+ { 2, 2, Expr::STRING_RESULT, &nsGkAtoms::substringBefore }, // SUBSTRING_BEFORE
+ { 3, 3, Expr::STRING_RESULT, &nsGkAtoms::translate }, // TRANSLATE
+
+ { 0, 1, Expr::NUMBER_RESULT, &nsGkAtoms::number }, // NUMBER
+ { 1, 1, Expr::NUMBER_RESULT, &nsGkAtoms::round }, // ROUND
+ { 1, 1, Expr::NUMBER_RESULT, &nsGkAtoms::floor }, // FLOOR
+ { 1, 1, Expr::NUMBER_RESULT, &nsGkAtoms::ceiling }, // CEILING
+ { 1, 1, Expr::NUMBER_RESULT, &nsGkAtoms::sum }, // SUM
+
+ { 1, 1, Expr::BOOLEAN_RESULT, &nsGkAtoms::boolean }, // BOOLEAN
+ { 0, 0, Expr::BOOLEAN_RESULT, &nsGkAtoms::_false }, // _FALSE
+ { 1, 1, Expr::BOOLEAN_RESULT, &nsGkAtoms::lang }, // LANG
+ { 1, 1, Expr::BOOLEAN_RESULT, &nsGkAtoms::_not }, // _NOT
+ { 0, 0, Expr::BOOLEAN_RESULT, &nsGkAtoms::_true } // _TRUE
+};
+
+
+/*
+ * Evaluates this Expr based on the given context node and processor state
+ * @param context the context node for evaluation of this Expr
+ * @param ps the ContextState containing the stack information needed
+ * for evaluation
+ * @return the result of the evaluation
+ */
+nsresult
+txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
+{
+ *aResult = nullptr;
+
+ if (!requireParams(descriptTable[mType].mMinParams,
+ descriptTable[mType].mMaxParams,
+ aContext)) {
+ return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
+ }
+
+ nsresult rv = NS_OK;
+ switch (mType) {
+ case COUNT:
+ {
+ RefPtr<txNodeSet> nodes;
+ rv = evaluateToNodeSet(mParams[0], aContext,
+ getter_AddRefs(nodes));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aContext->recycler()->getNumberResult(nodes->size(),
+ aResult);
+ }
+ case ID:
+ {
+ RefPtr<txAExprResult> exprResult;
+ rv = mParams[0]->evaluate(aContext, getter_AddRefs(exprResult));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ RefPtr<txNodeSet> resultSet;
+ rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ txXPathTreeWalker walker(aContext->getContextNode());
+
+ if (exprResult->getResultType() == txAExprResult::NODESET) {
+ txNodeSet* nodes = static_cast<txNodeSet*>
+ (static_cast<txAExprResult*>
+ (exprResult));
+ int32_t i;
+ for (i = 0; i < nodes->size(); ++i) {
+ nsAutoString idList;
+ txXPathNodeUtils::appendNodeValue(nodes->get(i), idList);
+ nsWhitespaceTokenizer tokenizer(idList);
+ while (tokenizer.hasMoreTokens()) {
+ if (walker.moveToElementById(tokenizer.nextToken())) {
+ resultSet->add(walker.getCurrentPosition());
+ }
+ }
+ }
+ }
+ else {
+ nsAutoString idList;
+ exprResult->stringValue(idList);
+ nsWhitespaceTokenizer tokenizer(idList);
+ while (tokenizer.hasMoreTokens()) {
+ if (walker.moveToElementById(tokenizer.nextToken())) {
+ resultSet->add(walker.getCurrentPosition());
+ }
+ }
+ }
+
+ *aResult = resultSet;
+ NS_ADDREF(*aResult);
+
+ return NS_OK;
+ }
+ case LAST:
+ {
+ return aContext->recycler()->getNumberResult(aContext->size(),
+ aResult);
+ }
+ case LOCAL_NAME:
+ case NAME:
+ case NAMESPACE_URI:
+ {
+ // Check for optional arg
+ RefPtr<txNodeSet> nodes;
+ if (!mParams.IsEmpty()) {
+ rv = evaluateToNodeSet(mParams[0], aContext,
+ getter_AddRefs(nodes));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (nodes->isEmpty()) {
+ aContext->recycler()->getEmptyStringResult(aResult);
+
+ return NS_OK;
+ }
+ }
+
+ const txXPathNode& node = nodes ? nodes->get(0) :
+ aContext->getContextNode();
+ switch (mType) {
+ case LOCAL_NAME:
+ {
+ StringResult* strRes = nullptr;
+ rv = aContext->recycler()->getStringResult(&strRes);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ *aResult = strRes;
+ txXPathNodeUtils::getLocalName(node, strRes->mValue);
+
+ return NS_OK;
+ }
+ case NAMESPACE_URI:
+ {
+ StringResult* strRes = nullptr;
+ rv = aContext->recycler()->getStringResult(&strRes);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ *aResult = strRes;
+ txXPathNodeUtils::getNamespaceURI(node, strRes->mValue);
+
+ return NS_OK;
+ }
+ case NAME:
+ {
+ // XXX Namespace: namespaces have a name
+ if (txXPathNodeUtils::isAttribute(node) ||
+ txXPathNodeUtils::isElement(node) ||
+ txXPathNodeUtils::isProcessingInstruction(node)) {
+ StringResult* strRes = nullptr;
+ rv = aContext->recycler()->getStringResult(&strRes);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ *aResult = strRes;
+ txXPathNodeUtils::getNodeName(node, strRes->mValue);
+ }
+ else {
+ aContext->recycler()->getEmptyStringResult(aResult);
+ }
+
+ return NS_OK;
+ }
+ default:
+ {
+ MOZ_CRASH("Unexpected mType?!");
+ }
+ }
+ MOZ_CRASH("Inner mType switch should have returned!");
+ }
+ case POSITION:
+ {
+ return aContext->recycler()->getNumberResult(aContext->position(),
+ aResult);
+ }
+
+ // String functions
+
+ case CONCAT:
+ {
+ RefPtr<StringResult> strRes;
+ rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t i, len = mParams.Length();
+ for (i = 0; i < len; ++i) {
+ rv = mParams[i]->evaluateToString(aContext, strRes->mValue);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ NS_ADDREF(*aResult = strRes);
+
+ return NS_OK;
+ }
+ case CONTAINS:
+ {
+ nsAutoString arg2;
+ rv = mParams[1]->evaluateToString(aContext, arg2);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (arg2.IsEmpty()) {
+ aContext->recycler()->getBoolResult(true, aResult);
+ }
+ else {
+ nsAutoString arg1;
+ rv = mParams[0]->evaluateToString(aContext, arg1);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aContext->recycler()->getBoolResult(FindInReadable(arg2, arg1),
+ aResult);
+ }
+
+ return NS_OK;
+ }
+ case NORMALIZE_SPACE:
+ {
+ nsAutoString resultStr;
+ if (!mParams.IsEmpty()) {
+ rv = mParams[0]->evaluateToString(aContext, resultStr);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ else {
+ txXPathNodeUtils::appendNodeValue(aContext->getContextNode(),
+ resultStr);
+ }
+
+ RefPtr<StringResult> strRes;
+ rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool addSpace = false;
+ bool first = true;
+ strRes->mValue.SetCapacity(resultStr.Length());
+ char16_t c;
+ uint32_t src;
+ for (src = 0; src < resultStr.Length(); src++) {
+ c = resultStr.CharAt(src);
+ if (XMLUtils::isWhitespace(c)) {
+ addSpace = true;
+ }
+ else {
+ if (addSpace && !first)
+ strRes->mValue.Append(char16_t(' '));
+
+ strRes->mValue.Append(c);
+ addSpace = false;
+ first = false;
+ }
+ }
+ *aResult = strRes;
+ NS_ADDREF(*aResult);
+
+ return NS_OK;
+ }
+ case STARTS_WITH:
+ {
+ nsAutoString arg2;
+ rv = mParams[1]->evaluateToString(aContext, arg2);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool result = false;
+ if (arg2.IsEmpty()) {
+ result = true;
+ }
+ else {
+ nsAutoString arg1;
+ rv = mParams[0]->evaluateToString(aContext, arg1);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ result = StringBeginsWith(arg1, arg2);
+ }
+
+ aContext->recycler()->getBoolResult(result, aResult);
+
+ return NS_OK;
+ }
+ case STRING:
+ {
+ RefPtr<StringResult> strRes;
+ rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!mParams.IsEmpty()) {
+ rv = mParams[0]->evaluateToString(aContext, strRes->mValue);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ else {
+ txXPathNodeUtils::appendNodeValue(aContext->getContextNode(),
+ strRes->mValue);
+ }
+
+ NS_ADDREF(*aResult = strRes);
+
+ return NS_OK;
+ }
+ case STRING_LENGTH:
+ {
+ nsAutoString resultStr;
+ if (!mParams.IsEmpty()) {
+ rv = mParams[0]->evaluateToString(aContext, resultStr);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ else {
+ txXPathNodeUtils::appendNodeValue(aContext->getContextNode(),
+ resultStr);
+ }
+ rv = aContext->recycler()->getNumberResult(resultStr.Length(),
+ aResult);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+ }
+ case SUBSTRING:
+ {
+ nsAutoString src;
+ rv = mParams[0]->evaluateToString(aContext, src);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ double start;
+ rv = evaluateToNumber(mParams[1], aContext, &start);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // check for NaN or +/-Inf
+ if (mozilla::IsNaN(start) ||
+ mozilla::IsInfinite(start) ||
+ start >= src.Length() + 0.5) {
+ aContext->recycler()->getEmptyStringResult(aResult);
+
+ return NS_OK;
+ }
+
+ start = floor(start + 0.5) - 1;
+
+ double end;
+ if (mParams.Length() == 3) {
+ rv = evaluateToNumber(mParams[2], aContext, &end);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ end += start;
+ if (mozilla::IsNaN(end) || end < 0) {
+ aContext->recycler()->getEmptyStringResult(aResult);
+
+ return NS_OK;
+ }
+
+ 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) {
+ aContext->recycler()->getEmptyStringResult(aResult);
+
+ return NS_OK;
+ }
+
+ return aContext->recycler()->getStringResult(
+ Substring(src, (uint32_t)start, (uint32_t)(end - start)),
+ aResult);
+ }
+ case SUBSTRING_AFTER:
+ {
+ nsAutoString arg1;
+ rv = mParams[0]->evaluateToString(aContext, arg1);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoString arg2;
+ rv = mParams[1]->evaluateToString(aContext, arg2);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (arg2.IsEmpty()) {
+ return aContext->recycler()->getStringResult(arg1, aResult);
+ }
+
+ int32_t idx = arg1.Find(arg2);
+ if (idx == kNotFound) {
+ aContext->recycler()->getEmptyStringResult(aResult);
+
+ return NS_OK;
+ }
+
+ const nsSubstring& result = Substring(arg1, idx + arg2.Length());
+ return aContext->recycler()->getStringResult(result, aResult);
+ }
+ case SUBSTRING_BEFORE:
+ {
+ nsAutoString arg2;
+ rv = mParams[1]->evaluateToString(aContext, arg2);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (arg2.IsEmpty()) {
+ aContext->recycler()->getEmptyStringResult(aResult);
+
+ return NS_OK;
+ }
+
+ nsAutoString arg1;
+ rv = mParams[0]->evaluateToString(aContext, arg1);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ int32_t idx = arg1.Find(arg2);
+ if (idx == kNotFound) {
+ aContext->recycler()->getEmptyStringResult(aResult);
+
+ return NS_OK;
+ }
+
+ return aContext->recycler()->getStringResult(StringHead(arg1, idx),
+ aResult);
+ }
+ case TRANSLATE:
+ {
+ nsAutoString src;
+ rv = mParams[0]->evaluateToString(aContext, src);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (src.IsEmpty()) {
+ aContext->recycler()->getEmptyStringResult(aResult);
+
+ return NS_OK;
+ }
+
+ RefPtr<StringResult> strRes;
+ rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ strRes->mValue.SetCapacity(src.Length());
+
+ nsAutoString oldChars, newChars;
+ rv = mParams[1]->evaluateToString(aContext, oldChars);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = mParams[2]->evaluateToString(aContext, newChars);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t i;
+ int32_t newCharsLength = (int32_t)newChars.Length();
+ for (i = 0; i < src.Length(); i++) {
+ int32_t idx = oldChars.FindChar(src.CharAt(i));
+ if (idx != kNotFound) {
+ if (idx < newCharsLength)
+ strRes->mValue.Append(newChars.CharAt((uint32_t)idx));
+ }
+ else {
+ strRes->mValue.Append(src.CharAt(i));
+ }
+ }
+
+ NS_ADDREF(*aResult = strRes);
+
+ return NS_OK;
+ }
+
+ // Number functions
+
+ case NUMBER:
+ {
+ double res;
+ if (!mParams.IsEmpty()) {
+ rv = evaluateToNumber(mParams[0], aContext, &res);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ else {
+ nsAutoString resultStr;
+ txXPathNodeUtils::appendNodeValue(aContext->getContextNode(),
+ resultStr);
+ res = txDouble::toDouble(resultStr);
+ }
+ return aContext->recycler()->getNumberResult(res, aResult);
+ }
+ case ROUND:
+ {
+ double dbl;
+ rv = evaluateToNumber(mParams[0], aContext, &dbl);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (mozilla::IsFinite(dbl)) {
+ if (mozilla::IsNegative(dbl) && dbl >= -0.5) {
+ dbl *= 0;
+ }
+ else {
+ dbl = floor(dbl + 0.5);
+ }
+ }
+
+ return aContext->recycler()->getNumberResult(dbl, aResult);
+ }
+ case FLOOR:
+ {
+ double dbl;
+ rv = evaluateToNumber(mParams[0], aContext, &dbl);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (mozilla::IsFinite(dbl) && !mozilla::IsNegativeZero(dbl))
+ dbl = floor(dbl);
+
+ return aContext->recycler()->getNumberResult(dbl, aResult);
+ }
+ case CEILING:
+ {
+ double dbl;
+ rv = evaluateToNumber(mParams[0], aContext, &dbl);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (mozilla::IsFinite(dbl)) {
+ if (mozilla::IsNegative(dbl) && dbl > -1)
+ dbl *= 0;
+ else
+ dbl = ceil(dbl);
+ }
+
+ return aContext->recycler()->getNumberResult(dbl, aResult);
+ }
+ case SUM:
+ {
+ RefPtr<txNodeSet> nodes;
+ nsresult rv = evaluateToNodeSet(mParams[0], aContext,
+ getter_AddRefs(nodes));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ double res = 0;
+ int32_t i;
+ for (i = 0; i < nodes->size(); ++i) {
+ nsAutoString resultStr;
+ txXPathNodeUtils::appendNodeValue(nodes->get(i), resultStr);
+ res += txDouble::toDouble(resultStr);
+ }
+ return aContext->recycler()->getNumberResult(res, aResult);
+ }
+
+ // Boolean functions
+
+ case BOOLEAN:
+ {
+ bool result;
+ nsresult rv = mParams[0]->evaluateToBool(aContext, result);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aContext->recycler()->getBoolResult(result, aResult);
+
+ return NS_OK;
+ }
+ case _FALSE:
+ {
+ aContext->recycler()->getBoolResult(false, aResult);
+
+ return NS_OK;
+ }
+ case LANG:
+ {
+ txXPathTreeWalker walker(aContext->getContextNode());
+
+ nsAutoString lang;
+ bool found;
+ do {
+ found = walker.getAttr(nsGkAtoms::lang, kNameSpaceID_XML,
+ lang);
+ } while (!found && walker.moveToParent());
+
+ if (!found) {
+ aContext->recycler()->getBoolResult(false, aResult);
+
+ return NS_OK;
+ }
+
+ nsAutoString arg;
+ rv = mParams[0]->evaluateToString(aContext, arg);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool result =
+ StringBeginsWith(lang, arg,
+ txCaseInsensitiveStringComparator()) &&
+ (lang.Length() == arg.Length() ||
+ lang.CharAt(arg.Length()) == '-');
+
+ aContext->recycler()->getBoolResult(result, aResult);
+
+ return NS_OK;
+ }
+ case _NOT:
+ {
+ bool result;
+ rv = mParams[0]->evaluateToBool(aContext, result);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aContext->recycler()->getBoolResult(!result, aResult);
+
+ return NS_OK;
+ }
+ case _TRUE:
+ {
+ aContext->recycler()->getBoolResult(true, aResult);
+
+ return NS_OK;
+ }
+ }
+
+ aContext->receiveError(NS_LITERAL_STRING("Internal error"),
+ NS_ERROR_UNEXPECTED);
+ return NS_ERROR_UNEXPECTED;
+}
+
+Expr::ResultType
+txCoreFunctionCall::getReturnType()
+{
+ return descriptTable[mType].mReturnType;
+}
+
+bool
+txCoreFunctionCall::isSensitiveTo(ContextSensitivity aContext)
+{
+ switch (mType) {
+ case COUNT:
+ case CONCAT:
+ case CONTAINS:
+ case STARTS_WITH:
+ case SUBSTRING:
+ case SUBSTRING_AFTER:
+ case SUBSTRING_BEFORE:
+ case TRANSLATE:
+ case ROUND:
+ case FLOOR:
+ case CEILING:
+ case SUM:
+ case BOOLEAN:
+ case _NOT:
+ case _FALSE:
+ case _TRUE:
+ {
+ return argsSensitiveTo(aContext);
+ }
+ case ID:
+ {
+ return (aContext & NODE_CONTEXT) ||
+ argsSensitiveTo(aContext);
+ }
+ case LAST:
+ {
+ return !!(aContext & SIZE_CONTEXT);
+ }
+ case LOCAL_NAME:
+ case NAME:
+ case NAMESPACE_URI:
+ case NORMALIZE_SPACE:
+ case STRING:
+ case STRING_LENGTH:
+ case NUMBER:
+ {
+ if (mParams.IsEmpty()) {
+ return !!(aContext & NODE_CONTEXT);
+ }
+ return argsSensitiveTo(aContext);
+ }
+ case POSITION:
+ {
+ return !!(aContext & POSITION_CONTEXT);
+ }
+ case LANG:
+ {
+ return (aContext & NODE_CONTEXT) ||
+ argsSensitiveTo(aContext);
+ }
+ }
+
+ NS_NOTREACHED("how'd we get here?");
+ return true;
+}
+
+// static
+bool
+txCoreFunctionCall::getTypeFromAtom(nsIAtom* aName, eType& aType)
+{
+ uint32_t i;
+ for (i = 0; i < ArrayLength(descriptTable); ++i) {
+ if (aName == *descriptTable[i].mName) {
+ aType = static_cast<eType>(i);
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#ifdef TX_TO_STRING
+nsresult
+txCoreFunctionCall::getNameAtom(nsIAtom** aAtom)
+{
+ NS_ADDREF(*aAtom = *descriptTable[mType].mName);
+ return NS_OK;
+}
+#endif