From 5fdda1cac684d85dc31850e365567e579c8ffd32 Mon Sep 17 00:00:00 2001 From: "peter%propagandism.org" Date: Tue, 18 Nov 2003 22:57:04 +0000 Subject: [PATCH] Fix for bug 151002 (abstract the content by a treewalker). Patch by me, with parts by Pike and sicking. r=sicking, sr=jst. git-svn-id: svn://10.0.0.236/trunk@149516 18797224-902f-48f8-a5cc-f745e15eee43 --- .../extensions/transformiix/build/Makefile.in | 14 +- .../source/base/txExpandedNameMap.cpp | 1 + .../source/base/txNamespaceMap.cpp | 2 +- .../transformiix/source/lib/Makefile.in | 2 +- .../source/main/txXSLTMarkDriver.cpp | 4 +- .../transformiix/source/xml/Makefile.in | 3 +- .../transformiix/source/xml/XMLUtils.cpp | 41 +- .../transformiix/source/xml/XMLUtils.h | 10 +- .../transformiix/source/xml/dom/Makefile.in | 4 +- .../transformiix/source/xml/dom/dom.h | 2 - .../source/xml/dom/standalone/dom.h | 5 + .../source/xml/parser/Makefile.in | 2 +- .../source/xml/parser/txXMLParser.cpp | 31 +- .../source/xml/parser/txXMLParser.h | 11 +- .../source/xpath/BooleanFunctionCall.cpp | 37 +- .../transformiix/source/xpath/Expr.h | 21 +- .../transformiix/source/xpath/ExprParser.cpp | 6 +- .../source/xpath/LocationStep.cpp | 280 ++++--- .../transformiix/source/xpath/Makefile.in | 5 +- .../source/xpath/NodeSetFunctionCall.cpp | 65 +- .../source/xpath/NumberFunctionCall.cpp | 7 +- .../transformiix/source/xpath/PathExpr.cpp | 50 +- .../source/xpath/PredicateList.cpp | 35 +- .../source/xpath/RelationalExpr.cpp | 26 +- .../transformiix/source/xpath/RootExpr.cpp | 17 +- .../source/xpath/StringFunctionCall.cpp | 19 +- .../transformiix/source/xpath/UnionExpr.cpp | 14 +- .../source/xpath/nsXPathExpression.cpp | 18 +- .../source/xpath/nsXPathExpression.h | 5 +- .../source/xpath/nsXPathResult.cpp | 9 +- .../source/xpath/txForwardContext.cpp | 4 +- .../source/xpath/txForwardContext.h | 8 +- .../source/xpath/txIXPathContext.h | 14 +- .../transformiix/source/xpath/txNameTest.cpp | 15 +- .../transformiix/source/xpath/txNodeSet.cpp | 764 ++++++++++-------- .../transformiix/source/xpath/txNodeSet.h | 196 +++-- .../source/xpath/txNodeSetContext.cpp | 4 +- .../source/xpath/txNodeTypeTest.cpp | 26 +- .../source/xpath/txResultRecycler.cpp | 6 +- .../source/xpath/txResultRecycler.h | 6 +- .../source/xpath/txSingleNodeContext.h | 10 +- .../xslt/functions/DocumentFunctionCall.cpp | 59 +- .../xslt/functions/GenerateIdFunctionCall.cpp | 72 +- .../source/xslt/functions/Makefile.in | 1 + .../source/xslt/functions/XSLTFunctions.h | 3 - .../source/xslt/functions/txKey.h | 20 +- .../xslt/functions/txKeyFunctionCall.cpp | 77 +- .../source/xslt/txExecutionState.cpp | 128 ++- .../source/xslt/txExecutionState.h | 38 +- .../source/xslt/txInstructions.cpp | 86 +- .../transformiix/source/xslt/txInstructions.h | 2 +- .../xslt/txMozillaStylesheetCompiler.cpp | 2 +- .../source/xslt/txMozillaXSLTProcessor.cpp | 62 +- .../source/xslt/txPatternParser.cpp | 4 +- .../source/xslt/txStandaloneXSLTProcessor.cpp | 29 +- .../source/xslt/txStandaloneXSLTProcessor.h | 6 +- .../transformiix/source/xslt/txStylesheet.cpp | 67 +- .../transformiix/source/xslt/txStylesheet.h | 9 +- .../transformiix/source/xslt/txXSLTNumber.cpp | 114 ++- .../transformiix/source/xslt/txXSLTNumber.h | 14 +- .../source/xslt/txXSLTPatterns.cpp | 100 ++- .../transformiix/source/xslt/txXSLTPatterns.h | 5 +- .../transformiix/source/xslt/util/Makefile.in | 1 + .../source/xslt/util/txNodeSorter.cpp | 1 - .../source/xslt/util/txNodeSorter.h | 2 +- 65 files changed, 1433 insertions(+), 1268 deletions(-) diff --git a/mozilla/extensions/transformiix/build/Makefile.in b/mozilla/extensions/transformiix/build/Makefile.in index 5a5e42983ff..7a5421e6ef2 100644 --- a/mozilla/extensions/transformiix/build/Makefile.in +++ b/mozilla/extensions/transformiix/build/Makefile.in @@ -64,12 +64,6 @@ LOBJS = ../source/base/Double.$(OBJ_SUFFIX) \ ../source/base/txExpandedNameMap.$(OBJ_SUFFIX) \ ../source/base/txNamespaceMap.$(OBJ_SUFFIX) \ ../source/base/txURIUtils.$(OBJ_SUFFIX) \ - ../source/xml/dom/mozImpl/MozillaAttr.$(OBJ_SUFFIX) \ - ../source/xml/dom/mozImpl/MozillaDocument.$(OBJ_SUFFIX) \ - ../source/xml/dom/mozImpl/MozillaElement.$(OBJ_SUFFIX) \ - ../source/xml/dom/mozImpl/MozillaNamedNodeMap.$(OBJ_SUFFIX) \ - ../source/xml/dom/mozImpl/MozillaNode.$(OBJ_SUFFIX) \ - ../source/xml/dom/mozImpl/MozillaProcInstruction.$(OBJ_SUFFIX) \ ../source/xpath/AdditiveExpr.$(OBJ_SUFFIX) \ ../source/xpath/AttributeValueTemplate.$(OBJ_SUFFIX) \ ../source/xpath/BooleanExpr.$(OBJ_SUFFIX) \ @@ -97,6 +91,7 @@ LOBJS = ../source/base/Double.$(OBJ_SUFFIX) \ ../source/xpath/StringFunctionCall.$(OBJ_SUFFIX) \ ../source/xpath/StringResult.$(OBJ_SUFFIX) \ ../source/xpath/txLiteralExpr.$(OBJ_SUFFIX) \ + ../source/xpath/txMozillaXPathTreeWalker.$(OBJ_SUFFIX) \ ../source/xpath/txNameTest.$(OBJ_SUFFIX) \ ../source/xpath/txNodeSet.$(OBJ_SUFFIX) \ ../source/xpath/txNodeTypeTest.$(OBJ_SUFFIX) \ @@ -107,7 +102,6 @@ LOBJS = ../source/base/Double.$(OBJ_SUFFIX) \ ../source/xpath/UnaryExpr.$(OBJ_SUFFIX) \ ../source/xpath/VariableRefExpr.$(OBJ_SUFFIX) \ ../source/xml/XMLUtils.$(OBJ_SUFFIX) \ - ../source/xml/XMLDOMUtils.$(OBJ_SUFFIX) \ ../source/xml/parser/txXMLParser.$(OBJ_SUFFIX) \ ../source/xslt/txBufferingHandler.$(OBJ_SUFFIX) \ ../source/xslt/txOutputFormat.$(OBJ_SUFFIX) \ @@ -150,6 +144,6 @@ EXTRA_DSO_LDOPTS += \ include $(topsrcdir)/config/rules.mk INCLUDES += -I$(srcdir)/../source/xslt -I$(srcdir)/../source/base \ - -I$(srcdir)/../source/xml -I$(srcdir)/../source/xml/dom \ - -I$(srcdir)/../source/xml/parser -I$(srcdir)/../source/xpath \ - -I$(srcdir)/../source/xslt/util -I$(srcdir)/../source/xslt/functions + -I$(srcdir)/../source/xml -I$(srcdir)/../source/xml/parser \ + -I$(srcdir)/../source/xpath -I$(srcdir)/../source/xslt/util \ + -I$(srcdir)/../source/xslt/functions diff --git a/mozilla/extensions/transformiix/source/base/txExpandedNameMap.cpp b/mozilla/extensions/transformiix/source/base/txExpandedNameMap.cpp index fcecadc882b..da716ad3d3b 100644 --- a/mozilla/extensions/transformiix/source/base/txExpandedNameMap.cpp +++ b/mozilla/extensions/transformiix/source/base/txExpandedNameMap.cpp @@ -37,6 +37,7 @@ * ***** END LICENSE BLOCK ***** */ #include "txExpandedNameMap.h" +#include "TxObject.h" #include const int kTxExpandedNameMapAllocSize = 16; diff --git a/mozilla/extensions/transformiix/source/base/txNamespaceMap.cpp b/mozilla/extensions/transformiix/source/base/txNamespaceMap.cpp index 3ca336b960b..495c00c16dd 100644 --- a/mozilla/extensions/transformiix/source/base/txNamespaceMap.cpp +++ b/mozilla/extensions/transformiix/source/base/txNamespaceMap.cpp @@ -37,8 +37,8 @@ * ***** END LICENSE BLOCK ***** */ #include "txNamespaceMap.h" -#include "dom.h" #include "txAtoms.h" +#include "txXPathNode.h" txNamespaceMap::txNamespaceMap() { diff --git a/mozilla/extensions/transformiix/source/lib/Makefile.in b/mozilla/extensions/transformiix/source/lib/Makefile.in index 97d79db63a1..b6dd1e79022 100644 --- a/mozilla/extensions/transformiix/source/lib/Makefile.in +++ b/mozilla/extensions/transformiix/source/lib/Makefile.in @@ -76,11 +76,11 @@ OBJS = ../base/Double.$(OBJ_SUFFIX) \ ../xpath/txForwardContext.$(OBJ_SUFFIX) \ ../xpath/txNodeSetContext.$(OBJ_SUFFIX) \ ../xpath/txResultRecycler.$(OBJ_SUFFIX) \ + ../xpath/txStandaloneXPathTreeWalker.$(OBJ_SUFFIX) \ ../xpath/UnionExpr.$(OBJ_SUFFIX) \ ../xpath/UnaryExpr.$(OBJ_SUFFIX) \ ../xpath/VariableRefExpr.$(OBJ_SUFFIX) \ ../xml/XMLUtils.$(OBJ_SUFFIX) \ - ../xml/XMLDOMUtils.$(OBJ_SUFFIX) \ ../xml/parser/txXMLParser.$(OBJ_SUFFIX) \ ../xslt/txBufferingHandler.$(OBJ_SUFFIX) \ ../xslt/txExecutionState.$(OBJ_SUFFIX) \ diff --git a/mozilla/extensions/transformiix/source/main/txXSLTMarkDriver.cpp b/mozilla/extensions/transformiix/source/main/txXSLTMarkDriver.cpp index e3cdb99faf3..0c10e3f205d 100644 --- a/mozilla/extensions/transformiix/source/main/txXSLTMarkDriver.cpp +++ b/mozilla/extensions/transformiix/source/main/txXSLTMarkDriver.cpp @@ -82,7 +82,7 @@ public: { if (!mXML || !mStylesheet || !mOut) return 1; - nsresult rv = transform(mXML, mStylesheet, *mOut, mObserver); + nsresult rv = transform(*mXML, mStylesheet, *mOut, mObserver); return NS_FAILED(rv); } int closeOutput () @@ -110,7 +110,7 @@ public: delete mOut; } private: - Document *mXML; + txXPathNode *mXML; nsRefPtr mStylesheet; SimpleErrorObserver mObserver; ofstream* mOut; diff --git a/mozilla/extensions/transformiix/source/xml/Makefile.in b/mozilla/extensions/transformiix/source/xml/Makefile.in index 8825d65eac2..70103ed7739 100644 --- a/mozilla/extensions/transformiix/source/xml/Makefile.in +++ b/mozilla/extensions/transformiix/source/xml/Makefile.in @@ -35,12 +35,13 @@ REQUIRES += dom \ content \ widget \ unicharutil \ + necko \ $(NULL) endif DIRS = dom parser -CPPSRCS = XMLDOMUtils.cpp XMLUtils.cpp +CPPSRCS = XMLUtils.cpp include $(topsrcdir)/config/rules.mk diff --git a/mozilla/extensions/transformiix/source/xml/XMLUtils.cpp b/mozilla/extensions/transformiix/source/xml/XMLUtils.cpp index d8765b50f33..58e21da890d 100644 --- a/mozilla/extensions/transformiix/source/xml/XMLUtils.cpp +++ b/mozilla/extensions/transformiix/source/xml/XMLUtils.cpp @@ -35,6 +35,7 @@ #include "txAtoms.h" #include "txStringUtils.h" #include "txNamespaceMap.h" +#include "txXPathTreeWalker.h" /** * Helper class for checking and partioning of QNames @@ -233,16 +234,6 @@ PRBool XMLUtils::isWhitespace(const nsAFlatString& aText) return PR_TRUE; } -/** - * Returns true if the given node's value has only whitespace characters - */ -PRBool XMLUtils::isWhitespace(Node* aNode) -{ - nsAutoString text; - aNode->getNodeValue(text); - return isWhitespace(text); -} - /** * Normalizes the value of a XML processing instruction **/ @@ -275,31 +266,21 @@ void XMLUtils::normalizePIValue(nsAString& piValue) } } -/* - * Walks up the document tree and returns true if the closest xml:space - * attribute is "preserve" - */ //static -MBool XMLUtils::getXMLSpacePreserve(Node* aNode) +MBool XMLUtils::getXMLSpacePreserve(const txXPathNode& aNode) { - NS_ASSERTION(aNode, "Calling preserveXMLSpace with NULL node!"); - nsAutoString value; - Node* parent = aNode; - while (parent) { - if (parent->getNodeType() == Node::ELEMENT_NODE) { - Element* elem = (Element*)parent; - if (elem->getAttr(txXMLAtoms::space, kNameSpaceID_XML, value)) { - if (TX_StringEqualsAtom(value, txXMLAtoms::preserve)) { - return MB_TRUE; - } - if (TX_StringEqualsAtom(value, txXMLAtoms::_default)) { - return MB_FALSE; - } + txXPathTreeWalker walker(aNode); + do { + if (walker.getAttr(txXMLAtoms::space, kNameSpaceID_XML, value)) { + if (TX_StringEqualsAtom(value, txXMLAtoms::preserve)) { + return PR_TRUE; + } + if (TX_StringEqualsAtom(value, txXMLAtoms::_default)) { + return PR_FALSE; } } - parent = parent->getParentNode(); - } + } while (walker.moveToParent()); return PR_FALSE; } diff --git a/mozilla/extensions/transformiix/source/xml/XMLUtils.h b/mozilla/extensions/transformiix/source/xml/XMLUtils.h index 00440da5b28..de149c7455e 100644 --- a/mozilla/extensions/transformiix/source/xml/XMLUtils.h +++ b/mozilla/extensions/transformiix/source/xml/XMLUtils.h @@ -31,10 +31,10 @@ #define MITRE_XMLUTILS_H #include "baseutils.h" -#include "dom.h" #include "nsDependentSubstring.h" #include "nsIAtom.h" #include "txError.h" +#include "txXPathNode.h" class txNamespaceMap; @@ -126,12 +126,6 @@ public: */ static PRBool isWhitespace(const nsAFlatString& aText); - /** - * Returns true if the given node's DOM nodevalue has only whitespace - * characters - */ - static PRBool isWhitespace(Node* aNode); - /** * Normalizes the value of a XML processingInstruction **/ @@ -156,7 +150,7 @@ public: * Walks up the document tree and returns true if the closest xml:space * attribute is "preserve" */ - static MBool getXMLSpacePreserve(Node* aNode); + static MBool getXMLSpacePreserve(const txXPathNode& aNode); }; #endif diff --git a/mozilla/extensions/transformiix/source/xml/dom/Makefile.in b/mozilla/extensions/transformiix/source/xml/dom/Makefile.in index ce6fa015f1f..bb4dadb5c35 100644 --- a/mozilla/extensions/transformiix/source/xml/dom/Makefile.in +++ b/mozilla/extensions/transformiix/source/xml/dom/Makefile.in @@ -26,9 +26,7 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk -ifndef TX_EXE -DIRS = mozImpl -else +ifdef TX_EXE DIRS = standalone endif diff --git a/mozilla/extensions/transformiix/source/xml/dom/dom.h b/mozilla/extensions/transformiix/source/xml/dom/dom.h index 5513e0550f5..3cddb5acc06 100644 --- a/mozilla/extensions/transformiix/source/xml/dom/dom.h +++ b/mozilla/extensions/transformiix/source/xml/dom/dom.h @@ -23,8 +23,6 @@ #ifdef TX_EXE #include "standalone/dom.h" -#else -#include "mozImpl/mozilladom.h" #endif #endif diff --git a/mozilla/extensions/transformiix/source/xml/dom/standalone/dom.h b/mozilla/extensions/transformiix/source/xml/dom/standalone/dom.h index cf9fa0304e0..cc075f7c9c9 100644 --- a/mozilla/extensions/transformiix/source/xml/dom/standalone/dom.h +++ b/mozilla/extensions/transformiix/source/xml/dom/standalone/dom.h @@ -149,6 +149,7 @@ class NodeList class NodeListDefinition : public NodeList { friend class NamedNodeMap; //-- LF + friend class txXPathTreeWalker; public: NodeListDefinition(); virtual ~NodeListDefinition(); @@ -188,6 +189,8 @@ class NamedNodeMap : public NodeListDefinition private: NodeListDefinition::ListItem* findListItemByName(const nsAString& name); + // txXPathTreeWalker is friend to speed up attr iterations + friend class txXPathTreeWalker; }; // @@ -268,6 +271,8 @@ class NodeDefinition : public Node, public NodeList protected: friend class Document; + friend class txXPathTreeWalker; + friend class txXPathNodeUtils; NodeDefinition(NodeType type, const nsAString& name, const nsAString& value, Document* owner); NodeDefinition(NodeType aType, const nsAString& aValue, diff --git a/mozilla/extensions/transformiix/source/xml/parser/Makefile.in b/mozilla/extensions/transformiix/source/xml/parser/Makefile.in index a8c9b0d529c..bd08f635c88 100644 --- a/mozilla/extensions/transformiix/source/xml/parser/Makefile.in +++ b/mozilla/extensions/transformiix/source/xml/parser/Makefile.in @@ -52,6 +52,6 @@ include $(topsrcdir)/config/rules.mk DEFINES += -DXML_DTD -DXML_UNICODE -INCLUDES += -I$(srcdir)/../../base -I$(srcdir)/../dom +INCLUDES += -I$(srcdir)/../../base -I$(srcdir)/../dom -I$(srcdir)/../../xpath libs:: $(OBJS) diff --git a/mozilla/extensions/transformiix/source/xml/parser/txXMLParser.cpp b/mozilla/extensions/transformiix/source/xml/parser/txXMLParser.cpp index 5eb2f5be1c2..6eab219f218 100644 --- a/mozilla/extensions/transformiix/source/xml/parser/txXMLParser.cpp +++ b/mozilla/extensions/transformiix/source/xml/parser/txXMLParser.cpp @@ -24,6 +24,8 @@ #include "txXMLParser.h" #include "txURIUtils.h" +#include "txXPathTreeWalker.h" + #ifndef TX_EXE #include "nsIDocument.h" #include "nsIDOMDocument.h" @@ -42,7 +44,7 @@ class txXMLParser { public: nsresult parse(istream& aInputStream, const nsAString& aUri, - Document** aResultDoc); + txXPathNode** aResultDoc); const nsAString& getErrorString(); /** @@ -68,8 +70,8 @@ class txXMLParser nsresult txParseDocumentFromURI(const nsAString& aHref, const nsAString& aReferrer, - Document* aLoader, nsAString& aErrMsg, - Document** aResult) + const txXPathNode& aLoader, nsAString& aErrMsg, + txXPathNode** aResult) { NS_ENSURE_ARG_POINTER(aResult); *aResult = nsnull; @@ -78,9 +80,8 @@ txParseDocumentFromURI(const nsAString& aHref, const nsAString& aReferrer, nsresult rv = NS_NewURI(getter_AddRefs(documentURI), aHref); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr theDocument; - nsCOMPtr loaderDocument = - do_QueryInterface(aLoader->getNSObj()); + nsIDocument* loaderDocument = txXPathNativeNode::getDocument(aLoader); + nsCOMPtr loadGroup = loaderDocument->GetDocumentLoadGroup(); nsIURI *loaderUri = loaderDocument->GetDocumentURL(); NS_ENSURE_TRUE(loaderUri, NS_ERROR_FAILURE); @@ -97,7 +98,7 @@ txParseDocumentFromURI(const nsAString& aHref, const nsAString& aReferrer, if (refUri) { http->SetReferrer(refUri); } - http->SetRequestHeader(NS_LITERAL_CSTRING("Accept"), + http->SetRequestHeader(NS_LITERAL_CSTRING("Accept"), NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"), PR_FALSE); @@ -108,15 +109,19 @@ txParseDocumentFromURI(const nsAString& aHref, const nsAString& aReferrer, do_GetService("@mozilla.org/content/syncload-dom-service;1", &rv); NS_ENSURE_SUCCESS(rv, rv); - rv = loader->LoadDocumentAsXML(channel, loaderUri, getter_AddRefs(theDocument)); + // Raw pointer, we want the resulting txXPathNode to hold a reference to + // the document. + nsIDOMDocument* theDocument = nsnull; + rv = loader->LoadDocumentAsXML(channel, loaderUri, &theDocument); if (NS_FAILED(rv) || !theDocument) { aErrMsg.Append(NS_LITERAL_STRING("Document load of ") + aHref + NS_LITERAL_STRING(" failed.")); return rv; } - *aResult = new Document(theDocument); + *aResult = txXPathNativeNode::createXPathNode(theDocument); if (!*aResult) { + NS_RELEASE(theDocument); return NS_ERROR_FAILURE; } @@ -133,7 +138,7 @@ txParseDocumentFromURI(const nsAString& aHref, const nsAString& aReferrer, #ifdef TX_EXE nsresult txParseFromStream(istream& aInputStream, const nsAString& aUri, - nsAString& aErrorString, Document** aResult) + nsAString& aErrorString, txXPathNode** aResult) { NS_ENSURE_ARG_POINTER(aResult); txXMLParser parser; @@ -211,7 +216,7 @@ externalEntityRefHandler(XML_Parser aParser, */ nsresult txXMLParser::parse(istream& aInputStream, const nsAString& aUri, - Document** aResultDoc) + txXPathNode** aResultDoc) { mErrorString.Truncate(); *aResultDoc = nsnull; @@ -263,9 +268,9 @@ txXMLParser::parse(istream& aInputStream, const nsAString& aUri, // clean up XML_ParserFree(mExpatParser); // ownership to the caller - *aResultDoc = mDocument; + *aResultDoc = txXPathNativeNode::createXPathNode(mDocument); mDocument = nsnull; - return NS_OK; + return *aResultDoc ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } const nsAString& diff --git a/mozilla/extensions/transformiix/source/xml/parser/txXMLParser.h b/mozilla/extensions/transformiix/source/xml/parser/txXMLParser.h index 76c15be3327..204b58e44b2 100644 --- a/mozilla/extensions/transformiix/source/xml/parser/txXMLParser.h +++ b/mozilla/extensions/transformiix/source/xml/parser/txXMLParser.h @@ -25,12 +25,15 @@ #ifndef MITRE_XMLPARSER_H #define MITRE_XMLPARSER_H -#include "dom.h" +#include "baseutils.h" #ifdef TX_EXE #include #endif +class nsAString; +class txXPathNode; + /** * API to load XML files into DOM datastructures. * Parsing is either done by expat, or by expat via the synchloaderservice @@ -42,8 +45,8 @@ */ extern "C" nsresult txParseDocumentFromURI(const nsAString& aHref, const nsAString& aReferrer, - Document* aLoader, nsAString& aErrMsg, - Document** aResult); + const txXPathNode& aLoader, nsAString& aErrMsg, + txXPathNode** aResult); #ifdef TX_EXE /** @@ -51,6 +54,6 @@ txParseDocumentFromURI(const nsAString& aHref, const nsAString& aReferrer, */ extern "C" nsresult txParseFromStream(istream& aInputStream, const nsAString& aUri, - nsAString& aErrorString, Document** aResult); + nsAString& aErrorString, txXPathNode** aResult); #endif #endif diff --git a/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp index fc577e556d8..e2b938e1f41 100644 --- a/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp @@ -33,6 +33,7 @@ #include "txAtoms.h" #include "txIXPathContext.h" #include "txStringUtils.h" +#include "txXPathTreeWalker.h" /** * Creates a default BooleanFunctionCall, which always evaluates to False @@ -71,27 +72,27 @@ BooleanFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) if (!requireParams(1, 1, aContext)) return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; + txXPathTreeWalker walker(aContext->getContextNode()); + nsAutoString lang; - Node* node = aContext->getContextNode(); - while (node) { - if (node->getNodeType() == Node::ELEMENT_NODE) { - Element* elem = (Element*)node; - if (elem->getAttr(txXMLAtoms::lang, - kNameSpaceID_XML, lang)) - break; - } - node = node->getParentNode(); + PRBool found; + do { + found = walker.getAttr(txXMLAtoms::lang, kNameSpaceID_XML, + lang); + } while (!found && walker.moveToParent()); + + if (!found) { + aContext->recycler()->getBoolResult(PR_FALSE, aResult); + + return NS_OK; } - MBool result = MB_FALSE; - if (node) { - nsAutoString arg; - evaluateToString((Expr*)iter.next(), aContext, arg); - result = arg.Equals(Substring(lang, 0, arg.Length()), - txCaseInsensitiveStringComparator()) && - (lang.Length() == arg.Length() || - lang.CharAt(arg.Length()) == '-'); - } + nsAutoString arg; + evaluateToString((Expr*)iter.next(), aContext, arg); + PRBool result = arg.Equals(Substring(lang, 0, arg.Length()), + txCaseInsensitiveStringComparator()) && + (lang.Length() == arg.Length() || + lang.CharAt(arg.Length()) == '-'); aContext->recycler()->getBoolResult(result, aResult); diff --git a/mozilla/extensions/transformiix/source/xpath/Expr.h b/mozilla/extensions/transformiix/source/xpath/Expr.h index 1640fc41374..79628aef80b 100644 --- a/mozilla/extensions/transformiix/source/xpath/Expr.h +++ b/mozilla/extensions/transformiix/source/xpath/Expr.h @@ -36,7 +36,6 @@ #define TRANSFRMX_EXPR_H #include "baseutils.h" -#include "dom.h" #include "List.h" #include "nsString.h" #include "nsIAtom.h" @@ -53,6 +52,7 @@ class txIParseContext; class txIMatchContext; class txIEvalContext; class txNodeSet; +class txXPathNode; /** * A Base Class for all XSL Expressions @@ -212,13 +212,14 @@ public: * standalone. The NodeTest node() is different to the * Pattern "node()" (document node isn't matched) */ - virtual MBool matches(Node* aNode, txIMatchContext* aContext) = 0; + virtual PRBool matches(const txXPathNode& aNode, + txIMatchContext* aContext) = 0; virtual double getDefaultPriority() = 0; virtual void toString(nsAString& aDest) = 0; }; #define TX_DECL_NODE_TEST \ - MBool matches(Node* aNode, txIMatchContext* aContext); \ + PRBool matches(const txXPathNode& aNode, txIMatchContext* aContext); \ double getDefaultPriority(); \ void toString(nsAString& aDest) @@ -233,7 +234,7 @@ public: * principal node type */ txNameTest(nsIAtom* aPrefix, nsIAtom* aLocalName, PRInt32 aNSID, - Node::NodeType aNodeType); + PRUint16 aNodeType); ~txNameTest(); @@ -243,7 +244,7 @@ private: nsCOMPtr mPrefix; nsCOMPtr mLocalName; PRInt32 mNamespace; - Node::NodeType mNodeType; + PRUint16 mNodeType; }; /* @@ -362,10 +363,10 @@ public: TX_DECL_EXPR; private: - void fromDescendants(Node* node, txIMatchContext* aContext, - txNodeSet* nodes); - void fromDescendantsRev(Node* node, txIMatchContext* aContext, - txNodeSet* nodes); + void fromDescendants(const txXPathNode& aNode, txIMatchContext* aCs, + txNodeSet* aNodes); + void fromDescendantsRev(const txXPathNode& aNode, txIMatchContext* aCs, + txNodeSet* aNodes); nsAutoPtr mNodeTest; LocationStepType mAxisIdentifier; @@ -619,7 +620,7 @@ private: * Selects from the descendants of the context node * all nodes that match the Expr */ - nsresult evalDescendants(Expr* aStep, Node* aNode, + nsresult evalDescendants(Expr* aStep, const txXPathNode& aNode, txIMatchContext* aContext, txNodeSet* resNodes); }; diff --git a/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp b/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp index e0ed411c763..65d2eb9346e 100644 --- a/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp +++ b/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp @@ -45,7 +45,7 @@ #include "txAtoms.h" #include "txIXPathContext.h" #include "txStringUtils.h" - +#include "txXPathNode.h" /** * Creates an Attribute Value Template using the given value @@ -692,11 +692,11 @@ txExprParser::createLocationStep(txExprLexer& lexer, txIParseContext* aContext, switch (axisIdentifier) { case LocationStep::ATTRIBUTE_AXIS: nodeTest = new txNameTest(prefix, lName, nspace, - Node::ATTRIBUTE_NODE); + txXPathNodeType::ATTRIBUTE_NODE); break; default: nodeTest = new txNameTest(prefix, lName, nspace, - Node::ELEMENT_NODE); + txXPathNodeType::ELEMENT_NODE); break; } NS_ENSURE_TRUE(nodeTest, NS_ERROR_OUT_OF_MEMORY); diff --git a/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp b/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp index de771cf7ffd..985f79fe86e 100644 --- a/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp +++ b/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp @@ -53,75 +53,92 @@ LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult) nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes)); NS_ENSURE_SUCCESS(rv, rv); - MBool reverse = MB_FALSE; + txXPathTreeWalker walker(aContext->getContextNode()); - Node* node = aContext->getContextNode(); switch (mAxisIdentifier) { - case ANCESTOR_AXIS : - node = node->getXPathParent(); - //-- do not break here - case ANCESTOR_OR_SELF_AXIS : - reverse = MB_TRUE; - while (node) { - if (mNodeTest->matches(node, aContext)) { - nodes->append(node); - } - node = node->getXPathParent(); - } - break; - case ATTRIBUTE_AXIS : + case ANCESTOR_AXIS: { - NamedNodeMap* atts = node->getAttributes(); - if (atts) { - for (PRUint32 i = 0; i < atts->getLength(); i++) { - Node* attr = atts->item(i); - if (attr->getNamespaceID() != kNameSpaceID_XMLNS && - mNodeTest->matches(attr, aContext)) - nodes->append(attr); + if (!walker.moveToParent()) { + break; + } + // do not break here + } + case ANCESTOR_OR_SELF_AXIS: + { + nodes->setReverse(); + + do { + if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) { + nodes->append(walker.getCurrentPosition()); + } + } while (walker.moveToParent()); + + break; + } + case ATTRIBUTE_AXIS: + { + if (!walker.moveToFirstAttribute()) { + break; + } + + do { + if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) { + nodes->append(walker.getCurrentPosition()); + } + } while (walker.moveToNextAttribute()); + break; + } + case DESCENDANT_OR_SELF_AXIS: + { + if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) { + nodes->append(walker.getCurrentPosition()); + } + // do not break here + } + case DESCENDANT_AXIS: + { + fromDescendants(walker.getCurrentPosition(), aContext, nodes); + break; + } + case FOLLOWING_AXIS: + { + if (walker.getNodeType() == txXPathNodeType::ATTRIBUTE_NODE) { + walker.moveToParent(); + fromDescendants(walker.getCurrentPosition(), aContext, nodes); + } + PRBool cont = PR_TRUE; + while (!walker.moveToNextSibling()) { + if (!walker.moveToParent()) { + cont = PR_FALSE; + break; + } + } + while (cont) { + if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) { + nodes->append(walker.getCurrentPosition()); + } + + fromDescendants(walker.getCurrentPosition(), aContext, nodes); + + while (!walker.moveToNextSibling()) { + if (!walker.moveToParent()) { + cont = PR_FALSE; + break; + } } } break; } - case DESCENDANT_OR_SELF_AXIS : - if (mNodeTest->matches(node, aContext)) - nodes->append(node); - //-- do not break here - case DESCENDANT_AXIS : - fromDescendants(node, aContext, nodes); - break; - case FOLLOWING_AXIS : + case FOLLOWING_SIBLING_AXIS: { - if ( node->getNodeType() == Node::ATTRIBUTE_NODE) { - node = node->getXPathParent(); - fromDescendants(node, aContext, nodes); - } - while (node && !node->getNextSibling()) { - node = node->getXPathParent(); - } - while (node) { - node = node->getNextSibling(); - - if (mNodeTest->matches(node, aContext)) - nodes->append(node); - - if (node->hasChildNodes()) - fromDescendants(node, aContext, nodes); - - while (node && !node->getNextSibling()) { - node = node->getParentNode(); + while (walker.moveToNextSibling()) { + if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) { + nodes->append(walker.getCurrentPosition()); } } break; } - case FOLLOWING_SIBLING_AXIS : - node = node->getNextSibling(); - while (node) { - if (mNodeTest->matches(node, aContext)) - nodes->append(node); - node = node->getNextSibling(); - } - break; - case NAMESPACE_AXIS : //-- not yet implemented + case NAMESPACE_AXIS: //-- not yet implemented #if 0 // XXX DEBUG OUTPUT cout << "namespace axis not yet implemented"<getXPathParent(); - if (mNodeTest->matches(parent, aContext)) - nodes->append(parent); + if (walker.moveToParent() && + mNodeTest->matches(walker.getCurrentPosition(), aContext)) { + nodes->append(walker.getCurrentPosition()); + } break; } - case PRECEDING_AXIS : - reverse = MB_TRUE; - while (node && !node->getPreviousSibling()) { - node = node->getXPathParent(); + case PRECEDING_AXIS: + { + nodes->setReverse(); + + PRBool cont = PR_TRUE; + while (!walker.moveToPreviousSibling()) { + if (!walker.moveToParent()) { + cont = PR_FALSE; + break; + } } - while (node) { - node = node->getPreviousSibling(); + while (cont) { + fromDescendantsRev(walker.getCurrentPosition(), aContext, nodes); - if (node->hasChildNodes()) - fromDescendantsRev(node, aContext, nodes); + if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) { + nodes->append(walker.getCurrentPosition()); + } - if (mNodeTest->matches(node, aContext)) - nodes->append(node); - - while (node && !node->getPreviousSibling()) { - node = node->getParentNode(); + while (!walker.moveToPreviousSibling()) { + if (!walker.moveToParent()) { + cont = PR_FALSE; + break; + } } } break; + } case PRECEDING_SIBLING_AXIS: - reverse = MB_TRUE; - node = node->getPreviousSibling(); - while (node) { - if (mNodeTest->matches(node, aContext)) - nodes->append(node); - node = node->getPreviousSibling(); - } - break; - case SELF_AXIS : - if (mNodeTest->matches(node, aContext)) - nodes->append(node); - break; - default: //-- Children Axis { - node = node->getFirstChild(); - while (node) { - if (mNodeTest->matches(node, aContext)) - nodes->append(node); - node = node->getNextSibling(); + nodes->setReverse(); + + while (walker.moveToPreviousSibling()) { + if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) { + nodes->append(walker.getCurrentPosition()); + } } break; } - } //-- switch + case SELF_AXIS: + { + if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) { + nodes->append(walker.getCurrentPosition()); + } + break; + } + default: // Children Axis + { + if (!walker.moveToFirstChild()) { + break; + } - //-- apply predicates + do { + if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) { + nodes->append(walker.getCurrentPosition()); + } + } while (walker.moveToNextSibling()); + break; + } + } + + // Apply predicates if (!isEmpty()) { rv = evaluatePredicates(nodes, aContext); NS_ENSURE_SUCCESS(rv, rv); } - if (reverse) - nodes->reverse(); + nodes->unsetReverse(); NS_ADDREF(*aResult = nodes); return NS_OK; } -void LocationStep::fromDescendants(Node* node, - txIMatchContext* cs, - txNodeSet* nodes) +void LocationStep::fromDescendants(const txXPathNode& aNode, + txIMatchContext* aCs, + txNodeSet* aNodes) { - if (!node) + txXPathTreeWalker walker(aNode); + if (!walker.moveToFirstChild()) { return; - - Node* child = node->getFirstChild(); - while (child) { - if (mNodeTest->matches(child, cs)) - nodes->append(child); - //-- check childs descendants - if (child->hasChildNodes()) - fromDescendants(child, cs, nodes); - - child = child->getNextSibling(); } + + do { + const txXPathNode& child = walker.getCurrentPosition(); + if (mNodeTest->matches(child, aCs)) { + aNodes->append(child); + } + fromDescendants(child, aCs, aNodes); + } while (walker.moveToNextSibling()); } -void LocationStep::fromDescendantsRev(Node* node, - txIMatchContext* cs, - txNodeSet* nodes) +void LocationStep::fromDescendantsRev(const txXPathNode& aNode, + txIMatchContext* aCs, + txNodeSet* aNodes) { - if (!node) + txXPathTreeWalker walker(aNode); + if (!walker.moveToLastChild()) { return; - - Node* child = node->getLastChild(); - while (child) { - //-- check childs descendants - if (child->hasChildNodes()) - fromDescendantsRev(child, cs, nodes); - - if (mNodeTest->matches(child, cs)) - nodes->append(child); - - child = child->getPreviousSibling(); } + + do { + const txXPathNode& child = walker.getCurrentPosition(); + fromDescendantsRev(child, aCs, aNodes); + + if (mNodeTest->matches(child, aCs)) { + aNodes->append(child); + } + + } while (walker.moveToPreviousSibling()); } /** diff --git a/mozilla/extensions/transformiix/source/xpath/Makefile.in b/mozilla/extensions/transformiix/source/xpath/Makefile.in index 0a91de1e4f0..e256ddc397c 100644 --- a/mozilla/extensions/transformiix/source/xpath/Makefile.in +++ b/mozilla/extensions/transformiix/source/xpath/Makefile.in @@ -79,7 +79,10 @@ CPPSRCS += nsXPathEvaluator.cpp \ nsXPathExpression.cpp \ nsXPathNSResolver.cpp \ nsXPathResult.cpp \ - nsXPath1Scheme.cpp + nsXPath1Scheme.cpp \ + txMozillaXPathTreeWalker.cpp +else +CPPSRCS += txStandaloneXPathTreeWalker.cpp endif include $(topsrcdir)/config/rules.mk diff --git a/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp index 425982b5be8..750f6bddef4 100644 --- a/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp @@ -33,11 +33,11 @@ */ #include "FunctionLib.h" +#include "nsAutoPtr.h" #include "txNodeSet.h" #include "txAtoms.h" #include "txIXPathContext.h" #include "txTokenizer.h" -#include "XMLDOMUtils.h" #ifndef TX_EXE #include "nsIDOMNode.h" #endif @@ -92,12 +92,7 @@ NodeSetFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet)); NS_ENSURE_SUCCESS(rv, rv); - Document* contextDoc = 0; - Node* contextNode = aContext->getContextNode(); - if (contextNode->getNodeType() == Node::DOCUMENT_NODE) - contextDoc = (Document*)contextNode; - else - contextDoc = contextNode->getOwnerDocument(); + txXPathTreeWalker walker(aContext->getContextNode()); if (exprResult->getResultType() == txAExprResult::NODESET) { txNodeSet* nodes = NS_STATIC_CAST(txNodeSet*, @@ -106,13 +101,12 @@ NodeSetFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) PRInt32 i; for (i = 0; i < nodes->size(); ++i) { nsAutoString idList; - XMLDOMUtils::getNodeValue(nodes->get(i), idList); + txXPathNodeUtils::appendNodeValue(nodes->get(i), idList); txTokenizer tokenizer(idList); while (tokenizer.hasMoreTokens()) { - Node* idNode = - contextDoc->getElementById(tokenizer.nextToken()); - if (idNode) - resultSet->add(idNode); + if (walker.moveToElementById(tokenizer.nextToken())) { + resultSet->add(walker.getCurrentPosition()); + } } } } @@ -121,10 +115,9 @@ NodeSetFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) exprResult->stringValue(idList); txTokenizer tokenizer(idList); while (tokenizer.hasMoreTokens()) { - Node* idNode = - contextDoc->getElementById(tokenizer.nextToken()); - if (idNode) - resultSet->add(idNode); + if (walker.moveToElementById(tokenizer.nextToken())) { + resultSet->add(walker.getCurrentPosition()); + } } } @@ -149,10 +142,9 @@ NodeSetFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; } - Node* node = 0; // Check for optional arg + nsRefPtr nodes; if (iter.hasNext()) { - nsRefPtr nodes; rv = evaluateToNodeSet((Expr*)iter.next(), aContext, getter_AddRefs(nodes)); NS_ENSURE_SUCCESS(rv, rv); @@ -162,12 +154,10 @@ NodeSetFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) return NS_OK; } - node = nodes->get(0); - } - else { - node = aContext->getContextNode(); } + const txXPathNode& node = nodes ? nodes->get(0) : + aContext->getContextNode(); switch (mType) { case LOCAL_NAME: { @@ -176,23 +166,8 @@ NodeSetFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) NS_ENSURE_SUCCESS(rv, rv); *aResult = strRes; -#ifdef TX_EXE - nsCOMPtr localNameAtom; - node->getLocalName(getter_AddRefs(localNameAtom)); - if (localNameAtom) { - // Node has a localName - localNameAtom->ToString(strRes->mValue); - } -#else - // The mozilla HTML-elements returns different casing for - // the localName-atom and .localName. Once we have a - // treeWalker it should have a getLocalName(nsAString&) - // function. - nsCOMPtr mozNode = - do_QueryInterface(node->getNSObj()); - NS_ASSERTION(mozNode, "wrapper doesn't wrap a nsIDOMNode"); - mozNode->GetLocalName(strRes->mValue); -#endif + txXPathNodeUtils::getLocalName(node, strRes->mValue); + return NS_OK; } case NAMESPACE_URI: @@ -202,16 +177,16 @@ NodeSetFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) NS_ENSURE_SUCCESS(rv, rv); *aResult = strRes; - node->getNamespaceURI(strRes->mValue); + txXPathNodeUtils::getNamespaceURI(node, strRes->mValue); return NS_OK; } case NAME: { - switch (node->getNodeType()) { - case Node::ATTRIBUTE_NODE: - case Node::ELEMENT_NODE: - case Node::PROCESSING_INSTRUCTION_NODE: + switch (txXPathNodeUtils::getNodeType(node)) { + case txXPathNodeType::ATTRIBUTE_NODE: + case txXPathNodeType::ELEMENT_NODE: + case txXPathNodeType::PROCESSING_INSTRUCTION_NODE: // XXX Namespace: namespaces have a name { StringResult* strRes = nsnull; @@ -219,7 +194,7 @@ NodeSetFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) NS_ENSURE_SUCCESS(rv, rv); *aResult = strRes; - node->getNodeName(strRes->mValue); + txXPathNodeUtils::getNodeName(node, strRes->mValue); return NS_OK; } diff --git a/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp index 7b824ca2d33..e19e1fb59c1 100644 --- a/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp @@ -38,7 +38,6 @@ #include "txNodeSet.h" #include "txAtoms.h" #include "txIXPathContext.h" -#include "XMLDOMUtils.h" /* * Creates a NumberFunctionCall of the given type @@ -121,7 +120,7 @@ NumberFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) PRInt32 i; for (i = 0; i < nodes->size(); ++i) { nsAutoString resultStr; - XMLDOMUtils::getNodeValue(nodes->get(i), resultStr); + txXPathNodeUtils::appendNodeValue(nodes->get(i), resultStr); res += Double::toDouble(resultStr); } return aContext->recycler()->getNumberResult(res, aResult); @@ -134,8 +133,8 @@ NumberFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) } else { nsAutoString resultStr; - XMLDOMUtils::getNodeValue(aContext->getContextNode(), - resultStr); + txXPathNodeUtils::appendNodeValue(aContext->getContextNode(), + resultStr); res = Double::toDouble(resultStr); } return aContext->recycler()->getNumberResult(res, aResult); diff --git a/mozilla/extensions/transformiix/source/xpath/PathExpr.cpp b/mozilla/extensions/transformiix/source/xpath/PathExpr.cpp index 41827cd4a4a..860dc39401b 100644 --- a/mozilla/extensions/transformiix/source/xpath/PathExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/PathExpr.cpp @@ -109,14 +109,14 @@ PathExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult) txNodeSetContext eContext(nodes, aContext); while (eContext.hasNext()) { eContext.next(); - Node* node = eContext.getContextNode(); - + nsRefPtr resNodes; if (pxi->pathOp == DESCENDANT_OP) { rv = aContext->recycler()->getNodeSet(getter_AddRefs(resNodes)); NS_ENSURE_SUCCESS(rv, rv); - rv = evalDescendants(pxi->expr, node, &eContext, resNodes); + rv = evalDescendants(pxi->expr, eContext.getContextNode(), + &eContext, resNodes); NS_ENSURE_SUCCESS(rv, rv); } else { @@ -141,7 +141,12 @@ PathExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult) getNonSharedNodeSet(oldSet, getter_AddRefs(tmpNodes)); NS_ENSURE_SUCCESS(rv, rv); - tmpNodes->add(resNodes); + oldSet.swap(resNodes); + rv = aContext->recycler()-> + getNonSharedNodeSet(oldSet, getter_AddRefs(resNodes)); + NS_ENSURE_SUCCESS(rv, rv); + + tmpNodes->addAndTransfer(resNodes); } } else { @@ -165,8 +170,8 @@ PathExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult) * all nodes that match the Expr **/ nsresult -PathExpr::evalDescendants(Expr* aStep, Node* aNode, txIMatchContext* aContext, - txNodeSet* resNodes) +PathExpr::evalDescendants(Expr* aStep, const txXPathNode& aNode, + txIMatchContext* aContext, txNodeSet* resNodes) { txSingleNodeContext eContext(aNode, aContext); nsRefPtr res; @@ -177,23 +182,34 @@ PathExpr::evalDescendants(Expr* aStep, Node* aNode, txIMatchContext* aContext, //XXX ErrorReport: report nonnodeset error return NS_ERROR_XSLT_NODESET_EXPECTED; } - resNodes->add(NS_STATIC_CAST(txNodeSet*, NS_STATIC_CAST(txAExprResult*, - res))); + + txNodeSet* oldSet = NS_STATIC_CAST(txNodeSet*, + NS_STATIC_CAST(txAExprResult*, res)); + nsRefPtr newSet; + rv = aContext->recycler()->getNonSharedNodeSet(oldSet, + getter_AddRefs(newSet)); + NS_ENSURE_SUCCESS(rv, rv); + + resNodes->addAndTransfer(newSet); MBool filterWS = aContext->isStripSpaceAllowed(aNode); - Node* child = aNode->getFirstChild(); - while (child) { + txXPathTreeWalker walker(aNode); + if (!walker.moveToFirstChild()) { + return NS_OK; + } + + do { if (!(filterWS && - (child->getNodeType() == Node::TEXT_NODE || - child->getNodeType() == Node::CDATA_SECTION_NODE) && - XMLUtils::isWhitespace(child))) { - rv = evalDescendants(aStep, child, aContext, resNodes); + (walker.getNodeType() == txXPathNodeType::TEXT_NODE || + walker.getNodeType() == txXPathNodeType::CDATA_SECTION_NODE) && + txXPathNodeUtils::isWhitespace(walker.getCurrentPosition()))) { + rv = evalDescendants(aStep, walker.getCurrentPosition(), aContext, + resNodes); NS_ENSURE_SUCCESS(rv, rv); } - child = child->getNextSibling(); - } - + } while (walker.moveToNextSibling()); + return NS_OK; } //-- evalDescendants diff --git a/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp b/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp index 84db54d5982..f2fce5aa1d5 100644 --- a/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp +++ b/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp @@ -67,10 +67,8 @@ PredicateList::evaluatePredicates(txNodeSet* nodes, txIMatchContext* aContext) { NS_ASSERTION(nodes, "called evaluatePredicates with NULL NodeSet"); - nsRefPtr newNodes; - nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(newNodes)); - NS_ENSURE_SUCCESS(rv, rv); - + nsresult rv = NS_OK; + txListIterator iter(&predicates); while (iter.hasNext() && !nodes->isEmpty()) { Expr* expr = (Expr*)iter.next(); @@ -80,31 +78,28 @@ PredicateList::evaluatePredicates(txNodeSet* nodes, * or, if the result is a number, add the node with the right * position */ - newNodes->clear(); + PRInt32 index = 0; while (predContext.hasNext()) { predContext.next(); nsRefPtr exprResult; rv = expr->evaluate(&predContext, getter_AddRefs(exprResult)); NS_ENSURE_SUCCESS(rv, rv); - switch(exprResult->getResultType()) { - case txAExprResult::NUMBER: - // handle default, [position() == numberValue()] - if ((double)predContext.position() == - exprResult->numberValue()) - newNodes->append(predContext.getContextNode()); - break; - default: - if (exprResult->booleanValue()) - newNodes->append(predContext.getContextNode()); - break; + // handle default, [position() == numberValue()] + if (exprResult->getResultType() == txAExprResult::NUMBER) { + if ((double)predContext.position() == exprResult->numberValue()) { + nodes->mark(index); + } } + else if (exprResult->booleanValue()) { + nodes->mark(index); + } + ++index; } - // Move new NodeSet to the current one - nodes->clear(); - nodes->append(newNodes); + // sweep the non-marked nodes + nodes->sweep(); } - + return NS_OK; } diff --git a/mozilla/extensions/transformiix/source/xpath/RelationalExpr.cpp b/mozilla/extensions/transformiix/source/xpath/RelationalExpr.cpp index 0d905fc3d2c..9760d240957 100644 --- a/mozilla/extensions/transformiix/source/xpath/RelationalExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/RelationalExpr.cpp @@ -29,7 +29,6 @@ #include "Expr.h" #include "txNodeSet.h" -#include "XMLDOMUtils.h" #include "txIXPathContext.h" /** @@ -58,7 +57,8 @@ RelationalExpr::compareResults(txIEvalContext* aContext, txAExprResult* aLeft, PRInt32 i; for (i = 0; i < nodeSet->size(); ++i) { strResult->mValue.Truncate(); - XMLDOMUtils::getNodeValue(nodeSet->get(i), strResult->mValue); + txXPathNodeUtils::appendNodeValue(nodeSet->get(i), + strResult->mValue); if (compareResults(aContext, strResult, aRight)) { return PR_TRUE; } @@ -82,7 +82,8 @@ RelationalExpr::compareResults(txIEvalContext* aContext, txAExprResult* aLeft, PRInt32 i; for (i = 0; i < nodeSet->size(); ++i) { strResult->mValue.Truncate(); - XMLDOMUtils::getNodeValue(nodeSet->get(i), strResult->mValue); + txXPathNodeUtils::appendNodeValue(nodeSet->get(i), + strResult->mValue); if (compareResults(aContext, aLeft, strResult)) { return PR_TRUE; } @@ -153,20 +154,27 @@ RelationalExpr::compareResults(txIEvalContext* aContext, txAExprResult* aLeft, switch (mOp) { case LESS_THAN: + { return leftDbl < rightDbl; - + } case LESS_OR_EQUAL: + { return leftDbl <= rightDbl; - - case GREATER_THAN : + } + case GREATER_THAN: + { return leftDbl > rightDbl; - + } case GREATER_OR_EQUAL: + { return leftDbl >= rightDbl; + } + default: + { + NS_NOTREACHED("We should have caught all cases"); + } } - NS_NOTREACHED("We should have caught all cases"); - return PR_FALSE; } diff --git a/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp b/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp index e4c62451c0a..e246469f420 100644 --- a/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp @@ -45,12 +45,21 @@ RootExpr::RootExpr(MBool aSerialize) { nsresult RootExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult) { - Node* context = aContext->getContextNode(); - if (context->getNodeType() != Node::DOCUMENT_NODE) { - context = context->getOwnerDocument(); + const txXPathNode& context = aContext->getContextNode(); + nsAutoPtr document(txXPathNodeUtils::getDocument(context)); + if (!document) { + nsRefPtr nodes; + aContext->recycler()->getNodeSet(getter_AddRefs(nodes)); + if (!nodes) { + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(*aResult = nodes); + + return NS_OK; } - return aContext->recycler()->getNodeSet(context, aResult); + return aContext->recycler()->getNodeSet(*document, aResult); } //-- evaluate /** diff --git a/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp index dc8eeee3a81..1d4282b7cbe 100644 --- a/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp @@ -33,8 +33,8 @@ #include "FunctionLib.h" #include "txAtoms.h" #include "txIXPathContext.h" -#include "XMLDOMUtils.h" #include "XMLUtils.h" +#include "txXPathTreeWalker.h" #include #include "nsReadableUtils.h" @@ -105,8 +105,8 @@ StringFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) if (iter.hasNext()) evaluateToString((Expr*)iter.next(), aContext, resultStr); else - XMLDOMUtils::getNodeValue(aContext->getContextNode(), - resultStr); + txXPathNodeUtils::appendNodeValue(aContext->getContextNode(), + resultStr); nsRefPtr strRes; rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes)); @@ -164,8 +164,8 @@ StringFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) if (iter.hasNext()) evaluateToString((Expr*)iter.next(), aContext, resultStr); else - XMLDOMUtils::getNodeValue(aContext->getContextNode(), - resultStr); + txXPathNodeUtils::appendNodeValue(aContext->getContextNode(), + resultStr); rv = aContext->recycler()->getNumberResult(resultStr.Length(), aResult); NS_ENSURE_SUCCESS(rv, rv); @@ -280,7 +280,12 @@ StringFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) nsAutoString src; evaluateToString((Expr*)iter.next(), aContext, src); + if (src.IsEmpty()) { + aContext->recycler()->getEmptyStringResult(aResult); + return NS_OK; + } + nsRefPtr strRes; rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes)); NS_ENSURE_SUCCESS(rv, rv); @@ -318,8 +323,8 @@ StringFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) if (iter.hasNext()) evaluateToString((Expr*)iter.next(), aContext, strRes->mValue); else - XMLDOMUtils::getNodeValue(aContext->getContextNode(), - strRes->mValue); + txXPathNodeUtils::appendNodeValue(aContext->getContextNode(), + strRes->mValue); *aResult = strRes; NS_ADDREF(*aResult); diff --git a/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp b/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp index 7e712acd927..efbf447af47 100644 --- a/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp @@ -24,8 +24,8 @@ */ #include "Expr.h" -#include "txNodeSet.h" #include "txIXPathContext.h" +#include "txNodeSet.h" //-------------/ //- UnionExpr -/ @@ -93,8 +93,16 @@ UnionExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult) //XXX ErrorReport: report nonnodeset error return NS_ERROR_XSLT_NODESET_EXPECTED; } - rv = nodes->add(NS_STATIC_CAST(txNodeSet*, NS_STATIC_CAST(txAExprResult*, - exprResult))); + + nsRefPtr resultSet, ownedSet; + resultSet = NS_STATIC_CAST(txNodeSet*, + NS_STATIC_CAST(txAExprResult*, exprResult)); + exprResult = nsnull; + rv = aContext->recycler()-> + getNonSharedNodeSet(resultSet, getter_AddRefs(ownedSet)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = nodes->addAndTransfer(ownedSet); NS_ENSURE_SUCCESS(rv, rv); } diff --git a/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.cpp b/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.cpp index 56824fb0a8a..d286d8315c7 100644 --- a/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.cpp +++ b/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.cpp @@ -48,7 +48,7 @@ #include "nsXPathResult.h" #include "nsDOMError.h" #include "txURIUtils.h" - +#include "txXPathTreeWalker.h" NS_IMPL_ADDREF(nsXPathExpression) NS_IMPL_RELEASE(nsXPathExpression) @@ -112,16 +112,12 @@ nsXPathExpression::Evaluate(nsIDOMNode *aContextNode, NS_ENSURE_ARG(aResult); *aResult = nsnull; - nsCOMPtr ownerDOMDocument; - aContextNode->GetOwnerDocument(getter_AddRefs(ownerDOMDocument)); - if (!ownerDOMDocument) { - ownerDOMDocument = do_QueryInterface(aContextNode); - NS_ENSURE_TRUE(ownerDOMDocument, NS_ERROR_FAILURE); + nsAutoPtr contextNode(txXPathNativeNode::createXPathNode(aContextNode)); + if (!contextNode) { + return NS_ERROR_OUT_OF_MEMORY; } - Document document(ownerDOMDocument); - Node* node = document.createWrapper(aContextNode); - EvalContextImpl eContext(node, mRecycler); + EvalContextImpl eContext(*contextNode, mRecycler); nsRefPtr exprResult; rv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult)); NS_ENSURE_SUCCESS(rv, rv); @@ -175,7 +171,7 @@ nsXPathExpression::EvalContextImpl::getVariable(PRInt32 aNamespace, return NS_ERROR_INVALID_ARG; } -MBool nsXPathExpression::EvalContextImpl::isStripSpaceAllowed(Node* aNode) +MBool nsXPathExpression::EvalContextImpl::isStripSpaceAllowed(const txXPathNode& aNode) { return MB_FALSE; } @@ -198,7 +194,7 @@ void nsXPathExpression::EvalContextImpl::receiveError(const nsAString& aMsg, // forward aMsg to console service? } -Node* nsXPathExpression::EvalContextImpl::getContextNode() +const txXPathNode& nsXPathExpression::EvalContextImpl::getContextNode() { return mContextNode; } diff --git a/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.h b/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.h index a3121bc7a9f..247e179c9c9 100644 --- a/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.h +++ b/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.h @@ -46,6 +46,7 @@ #include "nsAutoPtr.h" class Expr; +class txXPathNode; /** * A class for evaluating an XPath expression string @@ -70,7 +71,7 @@ private: class EvalContextImpl : public txIEvalContext { public: - EvalContextImpl(Node* aContextNode, txResultRecycler* aRecycler) + EvalContextImpl(const txXPathNode& aContextNode, txResultRecycler* aRecycler) : mContextNode(aContextNode), mLastError(NS_OK), mRecycler(aRecycler) @@ -89,7 +90,7 @@ private: TX_DECL_EVAL_CONTEXT; private: - Node* mContextNode; + const txXPathNode& mContextNode; nsresult mLastError; nsRefPtr mRecycler; }; diff --git a/mozilla/extensions/transformiix/source/xpath/nsXPathResult.cpp b/mozilla/extensions/transformiix/source/xpath/nsXPathResult.cpp index 73ecdbc6d11..b6330251d52 100644 --- a/mozilla/extensions/transformiix/source/xpath/nsXPathResult.cpp +++ b/mozilla/extensions/transformiix/source/xpath/nsXPathResult.cpp @@ -38,7 +38,6 @@ * ***** END LICENSE BLOCK ***** */ #include "nsXPathResult.h" -#include "dom.h" #include "ExprResult.h" #include "txNodeSet.h" #include "nsDOMError.h" @@ -292,9 +291,9 @@ nsXPathResult::SetExprResult(txAExprResult* aExprResult, PRUint16 aResultType) if (mResultType == FIRST_ORDERED_NODE_TYPE || mResultType == ANY_UNORDERED_NODE_TYPE) { - Node* node = nodeSet->get(0); - if (node) - rv = CallQueryInterface(node->getNSObj(), &mNode); + if (nodeSet->size() > 0) { + txXPathNativeNode::getNode(nodeSet->get(0), &mNode); + } } else { if (mResultType == UNORDERED_NODE_ITERATOR_TYPE || @@ -312,7 +311,7 @@ nsXPathResult::SetExprResult(txAExprResult* aExprResult, PRUint16 aResultType) nsCOMPtr node; PRInt32 i; for (i = 0; i < count; ++i) { - node = do_QueryInterface(nodeSet->get(i)->getNSObj()); + txXPathNativeNode::getNode(nodeSet->get(i), getter_AddRefs(node)); NS_ASSERTION(node, "node isn't an nsIDOMNode"); mElements->AppendObject(node); } diff --git a/mozilla/extensions/transformiix/source/xpath/txForwardContext.cpp b/mozilla/extensions/transformiix/source/xpath/txForwardContext.cpp index 2c5fe5395f6..7585e3f4f7e 100644 --- a/mozilla/extensions/transformiix/source/xpath/txForwardContext.cpp +++ b/mozilla/extensions/transformiix/source/xpath/txForwardContext.cpp @@ -39,7 +39,7 @@ #include "txForwardContext.h" #include "txNodeSet.h" -Node* txForwardContext::getContextNode() +const txXPathNode& txForwardContext::getContextNode() { return mContextNode; } @@ -63,7 +63,7 @@ nsresult txForwardContext::getVariable(PRInt32 aNamespace, nsIAtom* aLName, return mInner->getVariable(aNamespace, aLName, aResult); } -MBool txForwardContext::isStripSpaceAllowed(Node* aNode) +MBool txForwardContext::isStripSpaceAllowed(const txXPathNode& aNode) { NS_ASSERTION(mInner, "mInner is null!!!"); return mInner->isStripSpaceAllowed(aNode); diff --git a/mozilla/extensions/transformiix/source/xpath/txForwardContext.h b/mozilla/extensions/transformiix/source/xpath/txForwardContext.h index d86d75c07c7..356f9f16208 100644 --- a/mozilla/extensions/transformiix/source/xpath/txForwardContext.h +++ b/mozilla/extensions/transformiix/source/xpath/txForwardContext.h @@ -41,12 +41,14 @@ #include "txIXPathContext.h" #include "nsAutoPtr.h" -#include "txNodeSet.h" + +class txNodeSet; class txForwardContext : public txIEvalContext { public: - txForwardContext(txIMatchContext* aContext, Node* aContextNode, + txForwardContext(txIMatchContext* aContext, + const txXPathNode& aContextNode, txNodeSet* aContextNodeSet) : mInner(aContext), mContextNode(aContextNode), @@ -59,7 +61,7 @@ public: private: txIMatchContext* mInner; - Node* mContextNode; + const txXPathNode& mContextNode; nsRefPtr mContextSet; }; diff --git a/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h b/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h index 9b47daf35f7..9a5dff57c2e 100644 --- a/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h +++ b/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h @@ -43,10 +43,12 @@ #include "nsIAtom.h" #include "txError.h" -class txAExprResult; class FunctionCall; -class Node; +class nsAString; +class nsIAtom; +class txAExprResult; class txResultRecycler; +class txXPathNode; /* * txIParseContext @@ -114,7 +116,7 @@ public: * Is whitespace stripping allowed for the given node? * See http://www.w3.org/TR/xslt#strip */ - virtual MBool isStripSpaceAllowed(Node* aNode) = 0; + virtual MBool isStripSpaceAllowed(const txXPathNode& aNode) = 0; /** * Returns a pointer to the private context @@ -132,7 +134,7 @@ public: #define TX_DECL_MATCH_CONTEXT \ nsresult getVariable(PRInt32 aNamespace, nsIAtom* aLName, \ txAExprResult*& aResult); \ - MBool isStripSpaceAllowed(Node* aNode); \ + MBool isStripSpaceAllowed(const txXPathNode& aNode); \ void* getPrivateContext(); \ txResultRecycler* recycler(); \ void receiveError(const nsAString& aMsg, nsresult aRes) @@ -147,7 +149,7 @@ public: /* * Get the context node. */ - virtual Node* getContextNode() = 0; + virtual const txXPathNode& getContextNode() = 0; /* * Get the size of the context node set. @@ -163,7 +165,7 @@ public: #define TX_DECL_EVAL_CONTEXT \ TX_DECL_MATCH_CONTEXT; \ - Node* getContextNode(); \ + const txXPathNode& getContextNode(); \ PRUint32 size(); \ PRUint32 position() diff --git a/mozilla/extensions/transformiix/source/xpath/txNameTest.cpp b/mozilla/extensions/transformiix/source/xpath/txNameTest.cpp index bff91f825b3..24c56f28771 100644 --- a/mozilla/extensions/transformiix/source/xpath/txNameTest.cpp +++ b/mozilla/extensions/transformiix/source/xpath/txNameTest.cpp @@ -25,10 +25,11 @@ #include "Expr.h" #include "txAtoms.h" +#include "txXPathTreeWalker.h" #include "txIXPathContext.h" txNameTest::txNameTest(nsIAtom* aPrefix, nsIAtom* aLocalName, PRInt32 aNSID, - Node::NodeType aNodeType) + PRUint16 aNodeType) :mPrefix(aPrefix), mLocalName(aLocalName), mNamespace(aNSID), mNodeType(aNodeType) { @@ -41,12 +42,9 @@ txNameTest::~txNameTest() { } -/* - * Determines whether this txNodeTest matches the given node - */ -MBool txNameTest::matches(Node* aNode, txIMatchContext* aContext) +PRBool txNameTest::matches(const txXPathNode& aNode, txIMatchContext* aContext) { - if (!aNode || aNode->getNodeType() != mNodeType) + if (txXPathNodeUtils::getNodeType(aNode) != mNodeType) return MB_FALSE; // Totally wild? @@ -54,7 +52,7 @@ MBool txNameTest::matches(Node* aNode, txIMatchContext* aContext) return MB_TRUE; // Compare namespaces - if (aNode->getNamespaceID() != mNamespace) + if (txXPathNodeUtils::getNamespaceID(aNode) != mNamespace) return MB_FALSE; // Name wild? @@ -62,8 +60,7 @@ MBool txNameTest::matches(Node* aNode, txIMatchContext* aContext) return MB_TRUE; // Compare local-names - nsCOMPtr localName; - aNode->getLocalName(getter_AddRefs(localName)); + nsCOMPtr localName = txXPathNodeUtils::getLocalName(aNode); return localName == mLocalName; } diff --git a/mozilla/extensions/transformiix/source/xpath/txNodeSet.cpp b/mozilla/extensions/transformiix/source/xpath/txNodeSet.cpp index 45e7bc56cc2..311c35b08c8 100644 --- a/mozilla/extensions/transformiix/source/xpath/txNodeSet.cpp +++ b/mozilla/extensions/transformiix/source/xpath/txNodeSet.cpp @@ -31,95 +31,133 @@ */ #include "txNodeSet.h" -#include "dom.h" -#include "XMLDOMUtils.h" -#include +#include "TxLog.h" +#include "nsMemory.h" -static const int kTxNodeSetMinSize = 4; -static const int kTxNodeSetGrowFactor = 2; - -/* - * Implementation of an XPath NodeSet +/** + * Implementation of an XPath nodeset */ -/* - * Creates a new empty NodeSet - */ +static const PRInt32 kTxNodeSetMinSize = 4; +static const PRInt32 kTxNodeSetGrowFactor = 2; + +#define kForward 1 +#define kReversed -1 + txNodeSet::txNodeSet(txResultRecycler* aRecycler) : txAExprResult(aRecycler), - mElements(0), - mBufferSize(0), - mElementCount(0) + mStart(nsnull), + mEnd(nsnull), + mStartBuffer(nsnull), + mEndBuffer(nsnull), + mDirection(kForward), + mMarks(nsnull) { } -/* - * Creates a new NodeSet containing the supplied Node - */ -txNodeSet::txNodeSet(Node* aNode, txResultRecycler* aRecycler) +txNodeSet::txNodeSet(const txXPathNode& aNode, txResultRecycler* aRecycler) : txAExprResult(aRecycler), - mElements(new Node*[1]), - mBufferSize(1), - mElementCount(1) + mStart(nsnull), + mEnd(nsnull), + mStartBuffer(nsnull), + mEndBuffer(nsnull), + mDirection(kForward), + mMarks(nsnull) { - NS_ASSERTION(aNode, "missing node to txNodeSet::txNodeSet"); - if (!mElements) { - NS_ASSERTION(0, "out of memory"); - mBufferSize = 0; - mElementCount = 0; - } - else { - mElements[0] = aNode; + if (!ensureGrowSize(1)) { + return; } + + new(mStart) txXPathNode(aNode); + ++mEnd; } -/* - * Creates a new NodeSet, copying the Node references from the source - * NodeSet - */ txNodeSet::txNodeSet(const txNodeSet& aSource, txResultRecycler* aRecycler) : txAExprResult(aRecycler), - mElements(0), - mBufferSize(0), - mElementCount(0) + mStart(nsnull), + mEnd(nsnull), + mStartBuffer(nsnull), + mEndBuffer(nsnull), + mDirection(kForward), + mMarks(nsnull) { - append(&aSource); + append(aSource); } -/* - * Adds the specified Node to this NodeSet if it is not already in this - * NodeSet. The node is inserted according to document order. - * @param aNode the Node to add to the NodeSet - * @return errorcode. - */ -nsresult txNodeSet::add(Node* aNode) +txNodeSet::~txNodeSet() { - NS_ASSERTION(aNode, "missing node to txNodeSet::add"); - if (!aNode) - return NS_ERROR_NULL_POINTER; + delete [] mMarks; - MBool nonDup; - int pos = findPosition(aNode, 0, mElementCount - 1, nonDup); - if (nonDup) { - if (!ensureSize(mElementCount + 1)) - return NS_ERROR_OUT_OF_MEMORY; - memmove(mElements + pos + 1, - mElements + pos, - (mElementCount - pos) * sizeof(Node*)); - mElements[pos] = aNode; - ++mElementCount; + if (mStartBuffer) { + while (mStart < mEnd) { + mStart->~txXPathNode(); + ++mStart; + } + + nsMemory::Free(mStartBuffer); } +} + +nsresult txNodeSet::add(const txXPathNode& aNode) +{ + NS_ASSERTION(mDirection == kForward, + "only append(aNode) is supported on reversed nodesets"); + + if (isEmpty()) { + return append(aNode); + } + + PRBool dupe; + txXPathNode* pos = findPosition(aNode, mStart, mEnd, dupe); + + if (dupe) { + return NS_OK; + } + + // save pos, ensureGrowSize messes with the pointers + PRInt32 moveSize = mEnd - pos; + PRInt32 offset = pos - mStart; + if (!ensureGrowSize(1)) { + return NS_ERROR_OUT_OF_MEMORY; + } + // set pos to where it was + pos = mStart + offset; + + if (moveSize > 0) { + memmove(pos + 1, pos, moveSize * sizeof(txXPathNode)); + } + + new(pos) txXPathNode(aNode); + ++mEnd; + return NS_OK; } -/* - * Adds the nodes in specified NodeSet to this NodeSet. The resulting NodeSet - * is sorted in document order and does not contain any duplicate nodes. - * @param aNodes the NodeSet to add, must be in document order. - * @return true on success. false on failure. - */ +nsresult txNodeSet::add(const txNodeSet& aNodes) +{ + return add(aNodes, copyElements); +} -/* +nsresult txNodeSet::addAndTransfer(txNodeSet* aNodes) +{ + // failure is out-of-memory, transfer didn't happen + nsresult rv = add(*aNodes, transferElements); + NS_ENSURE_SUCCESS(rv, rv); + +#ifdef TX_DONT_RECYCLE_BUFFER + if (aNodes->mStartBuffer) { + nsMemory::Free(aNodes->mStartBuffer); + aNodes->mStartBuffer = aNodes->mEndBuffer = nsnull; + } +#endif + aNodes->mStart = aNodes->mEnd = aNodes->mStartBuffer; + + return NS_OK; +} + +/** + * add(aNodeSet, aTransferOp) + * * The code is optimized to make a minimum number of calls to * Node::compareDocumentPosition. The idea is this: * We have the two nodesets (number indicate "document position") @@ -129,267 +167,320 @@ nsresult txNodeSet::add(Node* aNode) * _ _ _ _ _ _ _ _ <- result * * - * We select the last node in the smallest nodeset and find where in the other - * nodeset it would be inserted. In this case we would take the 7 from the - * first nodeset and find the position between the 6 and 8 in the second. - * We then take the nodes after the insert-position and move it to the end of - * the resulting nodeset, and then do the same for the node from the smaller - * nodeset. Which in this case means that we'd first move the 8 and 9 nodes, - * and then the 7 node, giving us the following: + * When merging these nodesets into the result, the nodes are transfered + * in chunks to the end of the buffer so that each chunk does not contain + * a node from the other nodeset, in document order. + * + * We select the last non-transfered node in the first nodeset and find + * where in the other nodeset it would be inserted. In this case we would + * take the 7 from the first nodeset and find the position between the + * 6 and 8 in the second. We then take the nodes after the insert-position + * and transfer them to the end of the resulting nodeset. Which in this case + * means that we first transfered the 8 and 9 nodes, giving us the following: * - * 1 3 <- source 1 + * 1 3 7 <- source 1 * 2 3 6 <- source 2 - * _ _ _ _ _ 7 8 9 <- result + * _ _ _ _ _ _ 8 9 <- result + * + * The corresponding procedure is done for the second nodeset, that is + * the insertion position of the 6 in the first nodeset is found, which + * is between the 3 and the 7. The 7 is memmoved (as it stays within + * the same nodeset) to the result buffer. + * + * As the result buffer is filled from the end, it is safe to share the + * buffer between this nodeset and the result. * - * Repeat until one of the nodesets are empty. If we find a duplicate node - * when searching for where insertposition we skip the step where we move the - * node from the smaller nodeset to the resulting nodeset. So in this next - * step in the example we would only move the 3 and 6 nodes from the second - * nodeset and then just remove the 3 node from the first nodeset. Giving: - * - * 1 <- source 1 - * 2 <- source 2 - * _ _ _ 3 6 7 8 9 <- result - * - * We might therefor end up with some blanks in the bigining of the resulting - * nodeset, which we simply fix by moving all the nodes one step down. + * This is repeated until both of the nodesets are empty. + * + * If we find a duplicate node when searching for where insertposition we + * check for sequences of duplicate nodes, which can be optimized. + * */ -nsresult txNodeSet::add(const txNodeSet* aNodes) +nsresult txNodeSet::add(const txNodeSet& aNodes, transferOp aTransfer) { - NS_ASSERTION(aNodes, "missing nodeset to txNodeSet::add"); - if (!aNodes) - return NS_ERROR_NULL_POINTER; + NS_ASSERTION(mDirection == kForward, + "only append(aNode) is supported on reversed nodesets"); - if (aNodes->mElementCount == 0) + if (aNodes.isEmpty()) { return NS_OK; + } - // This is probably a rather common case, so lets try to shortcut - if (mElementCount == 0 || - mElements[mElementCount-1]->compareDocumentPosition(aNodes->mElements[0]) < 0) - return append(aNodes); - - if (!ensureSize(mElementCount + aNodes->mElementCount)) + if (!ensureGrowSize(aNodes.size())) { return NS_ERROR_OUT_OF_MEMORY; + } - // Index of last node in this nodeset - int thisPos = mElementCount - 1; - // Index of last node in other nodeset - int otherPos = aNodes->mElementCount - 1; - // Index in result where last insert was done. - int lastInsertPos = mElementCount + aNodes->mElementCount; - - while (thisPos >= 0 && otherPos >= 0) { - if (thisPos > otherPos) { - int pos; - MBool nonDup; - // Find where in the remaining nodes in this nodeset a node from - // the other nodeset should be inserted - pos = findPosition(aNodes->mElements[otherPos], 0, thisPos, - nonDup); + // This is probably a rather common case, so lets try to shortcut. + if (mStart == mEnd || + txXPathNodeUtils::comparePosition(mEnd[-1], *aNodes.mStart) < 0) { + aTransfer(mEnd, aNodes.mStart, aNodes.mEnd); + mEnd += aNodes.size(); - // Move nodes in this nodeset - lastInsertPos -= thisPos - pos + 1; - memmove(mElements + lastInsertPos, - mElements + pos, - (thisPos - pos + 1) * sizeof(Node*)); + return NS_OK; + } - // Copy node from the other nodeset unless it's a dup - if (nonDup) - mElements[--lastInsertPos] = aNodes->mElements[otherPos]; - - // Adjust positions in both nodesets - thisPos = pos - 1; - --otherPos; + // Last element in this nodeset + txXPathNode* thisPos = mEnd; + + // Last element of the other nodeset + txXPathNode* otherPos = aNodes.mEnd; + + // Pointer to the insertion point in this nodeset + txXPathNode* insertPos = mEndBuffer; + + PRBool dupe; + txXPathNode* pos; + PRInt32 count; + while (thisPos > mStart || otherPos > aNodes.mStart) { + // Find where the last remaining node of this nodeset would + // be inserted in the other nodeset. + if (thisPos > mStart) { + pos = findPosition(thisPos[-1], aNodes.mStart, otherPos, dupe); + + if (dupe) { + --thisPos; // this is already added + // check dupe sequence + while (thisPos > mStart && pos > aNodes.mStart && + thisPos[-1] == pos[-1]) { + --thisPos; + --pos; + } + } } else { - int pos; - MBool nonDup; - // Find where in the remaining nodes in the other nodeset a node - // from this nodeset should be inserted - pos = aNodes->findPosition(mElements[thisPos], 0, otherPos, - nonDup); + pos = aNodes.mStart; + } - // Copy nodes from other nodeset to this - lastInsertPos -= otherPos - pos + 1; - memcpy(mElements + lastInsertPos, - aNodes->mElements + pos, - (otherPos - pos + 1) * sizeof(Node*)); + // Transfer the otherNodes after the insertion point to the result + count = otherPos - pos; + if (count > 0) { + insertPos -= count; + aTransfer(insertPos, pos, otherPos); + otherPos -= count; + } - // Move node in this nodeset unless it's a dup - if (nonDup) - mElements[--lastInsertPos] = mElements[thisPos]; - - // Adjust positions in both nodesets - otherPos = pos - 1; - --thisPos; + // Find where the last remaining node of the otherNodeset would + // be inserted in this nodeset. + if (otherPos > aNodes.mStart) { + pos = findPosition(otherPos[-1], mStart, thisPos, dupe); + + if (dupe) { + --otherPos; // this is already added + // check dupe sequence + while (otherPos > aNodes.mStart && pos > mStart && + otherPos[-1] == pos[-1]) { + --otherPos; + --pos; + } + } + } + else { + pos = mStart; + } + + // Move the nodes from this nodeset after the insertion point + // to the result + count = thisPos - pos; + if (count > 0) { + insertPos -= count; + memmove(insertPos, pos, count * sizeof(txXPathNode)); + thisPos -= count; } } + mStart = insertPos; + mEnd = mEndBuffer; - if (thisPos >= 0) { - // There were some elements still left in this nodeset that need to - // be moved - lastInsertPos -= thisPos + 1; - memmove(mElements + lastInsertPos, - mElements, - (thisPos + 1) * sizeof(Node*)); - } - else if (otherPos >= 0) { - // There were some elements still left in the other nodeset that need - // to be copied - lastInsertPos -= otherPos + 1; - memcpy(mElements + lastInsertPos, - aNodes->mElements, - (otherPos + 1) * sizeof(Node*)); - } - - // if lastInsertPos != 0 then we have found some duplicates causing the - // first element to not be placed at mElements[0] - mElementCount += aNodes->mElementCount - lastInsertPos; - if (lastInsertPos) { - memmove(mElements, - mElements + lastInsertPos, - mElementCount * sizeof(Node*)); - } - return NS_OK; } -/* +/** * Append API * These functions should be used with care. * They are intended to be used when the caller assures that the resulting - * NodeSet remains in document order. + * nodeset remains in document order. * Abuse will break document order, and cause errors in the result. * These functions are significantly faster than the add API, as no - * Node::OrderInfo structs will be generated. + * order info operations will be performed. */ -/* - * Appends the specified Node to the end of this NodeSet - * @param aNode the Node to append to the NodeSet - * @return true on success. false on failure. - */ -nsresult txNodeSet::append(Node* aNode) +nsresult +txNodeSet::append(const txXPathNode& aNode) { - NS_ASSERTION(aNode, "missing node to txNodeSet::append"); - if (!aNode) - return NS_ERROR_NULL_POINTER; - - if (!ensureSize(mElementCount + 1)) + if (!ensureGrowSize(1)) { return NS_ERROR_OUT_OF_MEMORY; + } - mElements[mElementCount++] = aNode; + if (mDirection == kForward) { + new(mEnd) txXPathNode(aNode); + ++mEnd; + + return NS_OK; + } + + new(--mStart) txXPathNode(aNode); return NS_OK; } -/* - * Appends the nodes in the specified NodeSet to the end of this NodeSet - * @param aNodes the NodeSet to append to the NodeSet - * @return true on success. false on failure. - */ -nsresult txNodeSet::append(const txNodeSet* aNodes) +nsresult +txNodeSet::append(const txNodeSet& aNodes) { - NS_ASSERTION(aNodes, "missing nodeset to txNodeSet::append"); - if (!aNodes) - return NS_ERROR_NULL_POINTER; + NS_ASSERTION(mDirection == kForward, + "only append(aNode) is supported on reversed nodesets"); - if (!ensureSize(mElementCount + aNodes->mElementCount)) + if (aNodes.isEmpty()) { + return NS_OK; + } + + PRInt32 appended = aNodes.size(); + if (!ensureGrowSize(appended)) { return NS_ERROR_OUT_OF_MEMORY; + } - memcpy(mElements + mElementCount, - aNodes->mElements, - aNodes->mElementCount * sizeof(Node*)); - mElementCount += aNodes->mElementCount; + copyElements(mEnd, aNodes.mStart, aNodes.mEnd); + mEnd += appended; return NS_OK; } -/* - * Reverse the order of the nodes. - */ -void txNodeSet::reverse() +nsresult +txNodeSet::mark(PRInt32 aIndex) { - int i; - for (i = 0; i < mElementCount / 2; ++i) { - Node* tmp; - tmp = mElements[i]; - mElements[i] = mElements[mElementCount - 1 - i]; - mElements[mElementCount - 1 - i] = tmp; + NS_ASSERTION(aIndex >= 0 && mStart && mEnd - mStart > aIndex, + "index out of bounds"); + if (!mMarks) { + PRInt32 length = size(); + mMarks = new PRPackedBool[length]; + NS_ENSURE_TRUE(mMarks, NS_ERROR_OUT_OF_MEMORY); + memset(mMarks, 0, length * sizeof(PRPackedBool)); } + if (mDirection == kForward) { + mMarks[aIndex] = PR_TRUE; + } + else { + mMarks[size() - aIndex - 1] = PR_TRUE; + } + + return NS_OK; } -/* - * Returns the index of the specified Node, - * or -1 if the Node is not contained in the NodeSet - * @param aNode the Node to get the index for - * @return index of specified node or -1 if the node does not exist - */ -int txNodeSet::indexOf(Node* aNode) const +nsresult +txNodeSet::sweep() { - // XXX this doesn't fully work since attribute-nodes are broken - // and can't be pointer-compared. However it's the best we can - // do for now. - int i; - for (i = 0; i < mElementCount; ++i) { - if (mElements[i] == aNode) - return i; + if (!mMarks) { + // sweep everything + clear(); } + + PRInt32 chunk, pos = 0; + PRInt32 length = size(); + txXPathNode* insertion = mStartBuffer; + + while (pos < length) { + while (pos < length && !mMarks[pos]) { + // delete unmarked + mStart[pos].~txXPathNode(); + ++pos; + } + // find chunk to move + chunk = 0; + while (pos < length && mMarks[pos]) { + ++pos; + ++chunk; + } + // move chunk + if (chunk > 0) { + memmove(insertion, mStart + pos - chunk, + chunk * sizeof(txXPathNode)); + insertion += chunk; + } + } + mStart = mStartBuffer; + mEnd = insertion; + delete [] mMarks; + mMarks = nsnull; + + return NS_OK; +} + +void +txNodeSet::clear() +{ + while (mStart < mEnd) { + mStart->~txXPathNode(); + ++mStart; + } +#ifdef TX_DONT_RECYCLE_BUFFER + if (mStartBuffer) { + nsMemory::Free(mStartBuffer); + mStartBuffer = mEndBuffer = nsnull; + } +#endif + mStart = mEnd = mStartBuffer; + delete [] mMarks; + mMarks = nsnull; + mDirection = kForward; +} + +PRInt32 +txNodeSet::indexOf(const txXPathNode& aNode) const +{ + NS_ASSERTION(mDirection == kForward, + "only append(aNode) is supported on reversed nodesets"); + + if (!mStart || mStart == mEnd) { + return -1; + } + + PRInt32 counter = 0; + txXPathNode* pos = mStart; + for (; pos < mEnd; ++counter, ++pos) { + if (*pos == aNode) { + return counter; + } + } + return -1; } -/* - * Returns the Node at the specified position in this NodeSet. - * @param aIndex the position of the Node to return - * @return Node at specified position - */ -Node* txNodeSet::get(int aIndex) const +const txXPathNode& +txNodeSet::get(PRInt32 aIndex) const { - NS_ASSERTION(aIndex >= 0 && aIndex < mElementCount, - "invalid index in txNodeSet::get"); - if (aIndex < 0 || aIndex >= mElementCount) - return 0; + if (mDirection == kForward) { + return mStart[aIndex]; + } - return mElements[aIndex]; + return mEnd[-aIndex - 1]; } -/* - * Returns the type of ExprResult represented - * @return the type of ExprResult represented - */ -short txNodeSet::getResultType() +short +txNodeSet::getResultType() { return txAExprResult::NODESET; } -/* - * Converts this ExprResult to a Boolean (MBool) value - * @return the Boolean value - */ -MBool txNodeSet::booleanValue() +PRBool +txNodeSet::booleanValue() { - return mElementCount > 0; + return !isEmpty(); } - -/* - * Converts this ExprResult to a Number (double) value - * @return the Number value - */ -double txNodeSet::numberValue() +double +txNodeSet::numberValue() { nsAutoString str; stringValue(str); + return Double::toDouble(str); } -/* - * Creates a String representation of this ExprResult - * @param aStr the destination string to append the String representation to. - */ -void txNodeSet::stringValue(nsAString& aStr) +void +txNodeSet::stringValue(nsAString& aStr) { - if (mElementCount > 0) - XMLDOMUtils::getNodeValue(get(0), aStr); + NS_ASSERTION(mDirection == kForward, + "only append(aNode) is supported on reversed nodesets"); + if (isEmpty()) { + return; + } + txXPathNodeUtils::appendNodeValue(get(0), aStr); } nsAString* @@ -398,89 +489,132 @@ txNodeSet::stringValuePointer() return nsnull; } -/* - * Makes sure that the mElements buffer contains at least aSize elements. - * If a new allocation is required the elements are copied over to the new - * buffer - * @param aSize requested number of elements - * @return true if allocation succeded, false on out of memory - */ -MBool txNodeSet::ensureSize(int aSize) +PRBool txNodeSet::ensureGrowSize(PRInt32 aSize) { - if (aSize <= mBufferSize) - return MB_TRUE; + // check if there is enough place in the buffer as is + if (mDirection == kForward && aSize <= mEndBuffer - mEnd) { + return PR_TRUE; + } + + if (mDirection == kReversed && aSize <= mStart - mStartBuffer) { + return PR_TRUE; + } + + // check if we just have to align mStart to have enough space + PRInt32 oldSize = mEnd - mStart; + PRInt32 oldLength = mEndBuffer - mStartBuffer; + PRInt32 ensureSize = oldSize + aSize; + if (ensureSize <= oldLength) { + // just move the buffer + txXPathNode* dest = mStartBuffer; + if (mDirection == kReversed) { + dest = mEndBuffer - oldSize; + } + memmove(dest, mStart, oldSize * sizeof(txXPathNode)); + mStart = dest; + mEnd = dest + oldSize; + + return PR_TRUE; + } // This isn't 100% safe. But until someone manages to make a 1gig nodeset // it should be ok. - int newSize = mBufferSize > kTxNodeSetMinSize ? mBufferSize : - kTxNodeSetMinSize; - while (newSize < aSize) - newSize *= kTxNodeSetGrowFactor; + PRInt32 newLength = PR_MAX(oldLength, kTxNodeSetMinSize); - Node** newArr = new Node*[newSize]; - if (!newArr) - return MB_FALSE; - - if (mElementCount) - memcpy(newArr, mElements, mElementCount * sizeof(Node*)); + while (newLength < ensureSize) { + newLength *= kTxNodeSetGrowFactor; + } - delete [] mElements; - mElements = newArr; - mBufferSize = newSize; - - return MB_TRUE; + txXPathNode* newArr = NS_STATIC_CAST(txXPathNode*, + nsMemory::Alloc(newLength * + sizeof(txXPathNode))); + if (!newArr) { + return PR_FALSE; + } + + txXPathNode* dest = newArr; + if (mDirection == kReversed) { + dest += newLength - oldSize; + } + + if (oldSize > 0) { + memcpy(dest, mStart, oldSize * sizeof(txXPathNode)); + } + + if (mStartBuffer) { +#ifdef DEBUG + memset(mStartBuffer, 0, + (mEndBuffer - mStartBuffer) * sizeof(txXPathNode)); +#endif + nsMemory::Free(mStartBuffer); + } + + mStartBuffer = newArr; + mEndBuffer = mStartBuffer + newLength; + mStart = dest; + mEnd = dest + oldSize; + + return PR_TRUE; } -/* - * Finds position in the mElements buffer where a node should be inserted - * to keep the nodeset in document order. Searches the positions - * aFirst-aLast, including both aFirst and aLast. - * @param aNode Node to find insert position for - * @param aFirst First index to search, this index will be searched - * @param aLast Last index to search, this index will be searched - * @param aNonDup Out-param. Set to true if the node should be inserted, - * false if it already exists in the NodeSet. - * @return The index where to insert the node. The node should be - * inserted before the node at this index. This value is - * always >= aFirst and <= aLast + 1. This value is always - * set, even if aNode already exists in the NodeSet - */ -int txNodeSet::findPosition(Node* aNode, int aFirst, - int aLast, MBool& aNonDup) const +txXPathNode* +txNodeSet::findPosition(const txXPathNode& aNode, txXPathNode* aFirst, + txXPathNode* aLast, PRBool& aDupe) const { - NS_ASSERTION(aNode, "missing node in txNodeSet::findPosition"); - NS_ASSERTION(aFirst <= aLast+1 && aLast < mElementCount, - "bad position in txNodeSet::findPosition"); - - if (aLast - aFirst <= 1) { + aDupe = PR_FALSE; + if (aLast - aFirst <= 2) { // If we search 2 nodes or less there is no point in further divides - int pos; - for (pos = aFirst; pos <= aLast; ++pos) { - int cmp = aNode->compareDocumentPosition(mElements[pos]); + txXPathNode* pos = aFirst; + for (; pos < aLast; ++pos) { + PRIntn cmp = txXPathNodeUtils::comparePosition(aNode, *pos); if (cmp < 0) { - aNonDup = MB_TRUE; return pos; } if (cmp == 0) { - aNonDup = MB_FALSE; + aDupe = PR_TRUE; + return pos; } } - - aNonDup = MB_TRUE; return pos; } - - int midpos = (aFirst + aLast) / 2; - int cmp = aNode->compareDocumentPosition(mElements[midpos]); + + // (cannot add two pointers) + txXPathNode* midpos = aFirst + (aLast - aFirst) / 2; + PRIntn cmp = txXPathNodeUtils::comparePosition(aNode, *midpos); if (cmp == 0) { - aNonDup = MB_FALSE; + aDupe = PR_TRUE; + return midpos; } - if (cmp > 0) - return findPosition(aNode, midpos + 1, aLast, aNonDup); + if (cmp > 0) { + return findPosition(aNode, midpos + 1, aLast, aDupe); + } - return findPosition(aNode, aFirst, midpos - 1, aNonDup); + // midpos excluded as end of range + + return findPosition(aNode, aFirst, midpos, aDupe); +} + +/* static */ +void +txNodeSet::copyElements(txXPathNode* aDest, + const txXPathNode* aStart, const txXPathNode* aEnd) +{ + const txXPathNode* pos = aStart; + while (pos < aEnd) { + new(aDest) txXPathNode(*pos); + ++aDest; + ++pos; + } +} + +/* static */ +void +txNodeSet::transferElements(txXPathNode* aDest, + const txXPathNode* aStart, const txXPathNode* aEnd) +{ + memcpy(aDest, aStart, (aEnd - aStart) * sizeof(txXPathNode)); } diff --git a/mozilla/extensions/transformiix/source/xpath/txNodeSet.h b/mozilla/extensions/transformiix/source/xpath/txNodeSet.h index 494bdcb7175..56d083e1aee 100644 --- a/mozilla/extensions/transformiix/source/xpath/txNodeSet.h +++ b/mozilla/extensions/transformiix/source/xpath/txNodeSet.h @@ -27,183 +27,209 @@ * */ -/* +/** * Implementation of an XPath NodeSet */ -#ifndef TRANSFRMX_NODESET_H -#define TRANSFRMX_NODESET_H +#ifndef txNodeSet_h__ +#define txNodeSet_h__ #include "ExprResult.h" +#include "nsVoidArray.h" #include "txError.h" - -class Node; +#include "txXPathTreeWalker.h" class txNodeSet : public txAExprResult { - public: + // XXX TEMP + txNodeSet(); - txNodeSet(); // Not to be implemented - - /* + /** * Creates a new empty NodeSet */ txNodeSet(txResultRecycler* aRecycler); - /* - * Creates a new NodeSet containing the supplied node + /** + * Creates a new NodeSet with one node. */ - txNodeSet(Node* aNode, txResultRecycler* aRecycler); + txNodeSet(const txXPathNode& aNode, txResultRecycler* aRecycler); - /* - * Creates a new NodeSet, copying the Node references from the source - * NodeSet + /** + * Creates a new txNodeSet, copying the node references from the source + * NodeSet. */ txNodeSet(const txNodeSet& aSource, txResultRecycler* aRecycler); - /* - * Destructor for NodeSet, will not delete referenced Nodes + /** + * Destructor for txNodeSet, deletes the nodes. */ - virtual ~txNodeSet() - { - delete [] mElements; - } + virtual ~txNodeSet(); - /* - * Adds the specified Node to this NodeSet if it is not already in this - * NodeSet. The node is inserted according to document order. - * @param aNode the Node to add to the NodeSet + /** + * Adds the specified txXPathNode to this NodeSet if it is not already + * in this NodeSet. The node is inserted according to document order. + * + * @param aNode the txXPathNode to add to the NodeSet * @return errorcode. */ - nsresult add(Node* aNode); + nsresult add(const txXPathNode& aNode); - /* + /** * Adds the nodes in specified NodeSet to this NodeSet. The resulting * NodeSet is sorted in document order and does not contain any duplicate * nodes. + * * @param aNodes the NodeSet to add, must be in document order. * @return errorcode. */ - nsresult add(const txNodeSet* aNodes); + nsresult add(const txNodeSet& aNodes); + nsresult addAndTransfer(txNodeSet* aNodes); - /* + /** * Append API * These functions should be used with care. * They are intended to be used when the caller assures that the resulting * NodeSet remains in document order. * Abuse will break document order, and cause errors in the result. * These functions are significantly faster than the add API, as no - * Node::OrderInfo structs will be generated. + * order info operations will be performed. */ - /* + /** * Appends the specified Node to the end of this NodeSet * @param aNode the Node to append to the NodeSet * @return errorcode. */ - nsresult append(Node* aNode); + nsresult append(const txXPathNode& aNode); - /* + /** * Appends the nodes in the specified NodeSet to the end of this NodeSet * @param aNodes the NodeSet to append to the NodeSet * @return errorcode. */ - nsresult append(const txNodeSet* aNodes); + nsresult append(const txNodeSet& aNodes); - /* - * Reverse the order of the nodes. + /** + * API to implement reverse axes in LocationStep. + * + * Before adding nodes to the nodeset for a reversed axis, call + * setReverse(). This will make the append(aNode) and get() methods treat + * the nodeset as required. Do only call append(aNode), get(), mark() + * and sweep() while the nodeset is reversed. + * Afterwards, call unsetReverse(). The nodes are stored in document + * order internally. */ - void reverse(); - - /* - * Removes all nodes from this nodeset - */ - void clear() + void setReverse() { - mElementCount = 0; + mDirection = -1; + } + void unsetReverse() + { + mDirection = 1; } - /* + /** + * API to implement predicates in PredicateExpr + * + * mark(aIndex) marks the specified member of the nodeset. + * sweep() clears all members of the nodeset that haven't been + * marked before and clear the mMarks array. + */ + nsresult mark(PRInt32 aIndex); + nsresult sweep(); + + /** + * Removes all nodes from this nodeset + */ + void clear(); + + /** * Returns the index of the specified Node, * or -1 if the Node is not contained in the NodeSet * @param aNode the Node to get the index for * @return index of specified node or -1 if the node does not exist */ - int indexOf(Node* aNode) const; + PRInt32 indexOf(const txXPathNode& aNode) const; - /* + /** * Returns true if the specified Node is contained in the set. * @param aNode the Node to search for * @return true if specified Node is contained in the NodeSet */ - MBool contains(Node* aNode) const + PRBool contains(const txXPathNode& aNode) const { return indexOf(aNode) >= 0; } - /* - * Returns the Node at the specified position in this NodeSet. - * @param aIndex the position of the Node to return - * @return Node at specified position + /** + * Returns the Node at the specified node in this NodeSet. + * @param aIndex the node of the Node to return + * @return Node at specified node */ - Node* get(int aIndex) const; + const txXPathNode& get(PRInt32 aIndex) const; - /* + /** * Returns true if there are no Nodes in the NodeSet. * @return true if there are no Nodes in the NodeSet. */ - MBool isEmpty() const + PRBool isEmpty() const { - return mElementCount == 0; + return mStart ? mStart == mEnd : PR_TRUE; } - /* + /** * Returns the number of elements in the NodeSet * @return the number of elements in the NodeSet */ - int size() const + PRInt32 size() const { - return mElementCount; + return mStart ? mEnd - mStart : 0; } - /* - * Virtual methods from ExprResult - */ TX_DECL_EXPRRESULT private: + static void toString(const txNodeSet& aNodes, nsAString& aResult); - /* - * Makes sure that the mElements buffer contains at least aSize elements. - * If a new allocation is required the elements are copied over to the new - * buffer - * @param aSize requested number of elements - * @return true if allocation succeded, false on out of memory + /** + * Ensure that this nodeset can take another aSize nodes. + * + * Changes mStart and mEnd as well as mBufferStart and mBufferEnd. */ - MBool ensureSize(int aSize); + PRBool ensureGrowSize(PRInt32 aSize); - /* - * Finds position in the mElements buffer where a node should be inserted + /** + * Finds position in the buffer where a node should be inserted * to keep the nodeset in document order. Searches the positions - * aFirst-aLast, including both aFirst and aLast. - * @param aNode Node to find insert position for - * @param aFirst First index to search, this index will be searched - * @param aLast Last index to search, this index will be searched - * @param aPos out-param. Will be set to the index where to insert the - * node. The node should be inserted before the node at - * this index. This value is always >= aFirst and - * <= aLast + 1. This value is always set, even if aNode - * already exists in the NodeSet. - * @return true if the node should be inserted, false if it already exists - * in the NodeSet + * aFirst-aLast, including aFirst, but not aLast. + * @param aNode Node to find insert position for. + * @param aFirst First item of the search range, included. + * @param aLast Last item of the search range, excluded. + * @param aDupe out-param. Will be set to true if the node already + * exists in the NodeSet, false if it should be + * inserted. + * @return pointer where to insert the node. The node should be inserted + * before the given node. This value is always set, even if aNode + * already exists in the NodeSet */ - MBool findPosition(Node* aNode, int aFirst, int aLast, int& aPos) const; + txXPathNode* findPosition(const txXPathNode& aNode, + txXPathNode* aFirst, + txXPathNode* aLast, PRBool& aDupe) const; - Node** mElements; - int mBufferSize; - int mElementCount; + static void copyElements(txXPathNode* aDest, const txXPathNode* aStart, + const txXPathNode* aEnd); + static void transferElements(txXPathNode* aDest, const txXPathNode* aStart, + const txXPathNode* aEnd); + typedef void (*transferOp) (txXPathNode* aDest, const txXPathNode* aStart, + const txXPathNode* aEnd); + nsresult add(const txNodeSet& aNodes, transferOp aTransfer); + + txXPathNode *mStart, *mEnd, *mStartBuffer, *mEndBuffer; + PRInt32 mDirection; + // used for mark() and sweep() in predicates + PRPackedBool* mMarks; }; #endif diff --git a/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.cpp b/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.cpp index 87becdf3c26..e00135f5860 100644 --- a/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.cpp +++ b/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.cpp @@ -39,7 +39,7 @@ #include "txNodeSetContext.h" #include "txNodeSet.h" -Node* txNodeSetContext::getContextNode() +const txXPathNode& txNodeSetContext::getContextNode() { return mContextSet->get(mPosition - 1); } @@ -62,7 +62,7 @@ nsresult txNodeSetContext::getVariable(PRInt32 aNamespace, nsIAtom* aLName, return mInner->getVariable(aNamespace, aLName, aResult); } -MBool txNodeSetContext::isStripSpaceAllowed(Node* aNode) +MBool txNodeSetContext::isStripSpaceAllowed(const txXPathNode& aNode) { NS_ASSERTION(mInner, "mInner is null!!!"); return mInner->isStripSpaceAllowed(aNode); diff --git a/mozilla/extensions/transformiix/source/xpath/txNodeTypeTest.cpp b/mozilla/extensions/transformiix/source/xpath/txNodeTypeTest.cpp index 76e8fd5132b..a8c8e899d5f 100644 --- a/mozilla/extensions/transformiix/source/xpath/txNodeTypeTest.cpp +++ b/mozilla/extensions/transformiix/source/xpath/txNodeTypeTest.cpp @@ -26,6 +26,7 @@ #include "Expr.h" #include "nsIAtom.h" #include "txIXPathContext.h" +#include "txXPathTreeWalker.h" /* * Creates a new txNodeTypeTest of the given type @@ -44,34 +45,29 @@ void txNodeTypeTest::setNodeName(const nsAString& aName) mNodeName = do_GetAtom(aName); } -/* - * Determines whether this txNodeTest matches the given node - */ -MBool txNodeTypeTest::matches(Node* aNode, txIMatchContext* aContext) +PRBool txNodeTypeTest::matches(const txXPathNode& aNode, + txIMatchContext* aContext) { - if (!aNode) - return MB_FALSE; - - Node::NodeType type = (Node::NodeType)aNode->getNodeType(); + PRUint16 type = txXPathNodeUtils::getNodeType(aNode); switch (mNodeType) { case COMMENT_TYPE: - return type == Node::COMMENT_NODE; + return type == txXPathNodeType::COMMENT_NODE; case TEXT_TYPE: - return (type == Node::TEXT_NODE || - type == Node::CDATA_SECTION_NODE) && + return (type == txXPathNodeType::TEXT_NODE || + type == txXPathNodeType::CDATA_SECTION_NODE) && !aContext->isStripSpaceAllowed(aNode); case PI_TYPE: - if (type == Node::PROCESSING_INSTRUCTION_NODE) { + if (type == txXPathNodeType::PROCESSING_INSTRUCTION_NODE) { nsCOMPtr localName; return !mNodeName || - (aNode->getLocalName(getter_AddRefs(localName)) && + ((localName = txXPathNodeUtils::getLocalName(aNode)) && localName == mNodeName); } return MB_FALSE; case NODE_TYPE: - return ((type != Node::TEXT_NODE && - type != Node::CDATA_SECTION_NODE) || + return ((type != txXPathNodeType::TEXT_NODE && + type != txXPathNodeType::CDATA_SECTION_NODE) || !aContext->isStripSpaceAllowed(aNode)); } return MB_TRUE; diff --git a/mozilla/extensions/transformiix/source/xpath/txResultRecycler.cpp b/mozilla/extensions/transformiix/source/xpath/txResultRecycler.cpp index 0d2322c591c..5bceaba81cc 100644 --- a/mozilla/extensions/transformiix/source/xpath/txResultRecycler.cpp +++ b/mozilla/extensions/transformiix/source/xpath/txResultRecycler.cpp @@ -203,7 +203,7 @@ txResultRecycler::getNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult) else { *aResult = NS_STATIC_CAST(txNodeSet*, mNodeSetResults.pop()); (*aResult)->clear(); - (*aResult)->append(aNodeSet); + (*aResult)->append(*aNodeSet); (*aResult)->mRecycler = this; } NS_ADDREF(*aResult); @@ -212,7 +212,7 @@ txResultRecycler::getNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult) } nsresult -txResultRecycler::getNodeSet(Node* aNode, txAExprResult** aResult) +txResultRecycler::getNodeSet(const txXPathNode& aNode, txAExprResult** aResult) { if (mNodeSetResults.isEmpty()) { *aResult = new txNodeSet(aNode, this); @@ -231,7 +231,7 @@ txResultRecycler::getNodeSet(Node* aNode, txAExprResult** aResult) } nsresult -txResultRecycler::getNodeSet(Node* aNode, txNodeSet** aResult) +txResultRecycler::getNodeSet(const txXPathNode& aNode, txNodeSet** aResult) { if (mNodeSetResults.isEmpty()) { *aResult = new txNodeSet(aNode, this); diff --git a/mozilla/extensions/transformiix/source/xpath/txResultRecycler.h b/mozilla/extensions/transformiix/source/xpath/txResultRecycler.h index 01cbaebc981..5590c7e4c0d 100644 --- a/mozilla/extensions/transformiix/source/xpath/txResultRecycler.h +++ b/mozilla/extensions/transformiix/source/xpath/txResultRecycler.h @@ -45,7 +45,7 @@ class txAExprResult; class StringResult; class txNodeSet; -class Node; +class txXPathNode; class NumberResult; class BooleanResult; @@ -82,8 +82,8 @@ public: nsresult getStringResult(const nsAString& aValue, txAExprResult** aResult); nsresult getNodeSet(txNodeSet** aResult); nsresult getNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult); - nsresult getNodeSet(Node* aNode, txAExprResult** aResult); - nsresult getNodeSet(Node* aNode, txNodeSet** aResult); + nsresult getNodeSet(const txXPathNode& aNode, txAExprResult** aResult); + nsresult getNodeSet(const txXPathNode& aNode, txNodeSet** aResult); nsresult getNumberResult(double aValue, txAExprResult** aResult); /** diff --git a/mozilla/extensions/transformiix/source/xpath/txSingleNodeContext.h b/mozilla/extensions/transformiix/source/xpath/txSingleNodeContext.h index b56976398f8..b151c3ac466 100644 --- a/mozilla/extensions/transformiix/source/xpath/txSingleNodeContext.h +++ b/mozilla/extensions/transformiix/source/xpath/txSingleNodeContext.h @@ -44,11 +44,11 @@ class txSingleNodeContext : public txIEvalContext { public: - txSingleNodeContext(Node* aContextNode, txIMatchContext* aContext) + txSingleNodeContext(const txXPathNode& aContextNode, + txIMatchContext* aContext) : mNode(aContextNode), mInner(aContext) { - NS_ASSERTION(aContextNode, "context node must be given"); NS_ASSERTION(aContext, "txIMatchContext must be given"); } ~txSingleNodeContext() @@ -61,7 +61,7 @@ public: return mInner->getVariable(aNamespace, aLName, aResult); } - MBool isStripSpaceAllowed(Node* aNode) + MBool isStripSpaceAllowed(const txXPathNode& aNode) { NS_ASSERTION(mInner, "mInner is null!!!"); return mInner->isStripSpaceAllowed(aNode); @@ -91,7 +91,7 @@ public: #endif } - Node* getContextNode() + const txXPathNode& getContextNode() { return mNode; } @@ -107,7 +107,7 @@ public: } private: - Node* mNode; + const txXPathNode& mNode; txIMatchContext* mInner; }; diff --git a/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp index d93a5deb8ee..e9007a0e851 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp @@ -38,9 +38,9 @@ #include "txAtoms.h" #include "txIXPathContext.h" -#include "XMLDOMUtils.h" #include "XSLTFunctions.h" #include "txExecutionState.h" +#include "txURIUtils.h" /* * Creates a new DocumentFunctionCall. @@ -50,6 +50,43 @@ DocumentFunctionCall::DocumentFunctionCall(const nsAString& aBaseURI) { } +static void +retrieveNode(txExecutionState* aExecutionState, const nsAString& aUri, + const nsAString& aBaseUri, txNodeSet* aNodeSet) +{ + nsAutoString absUrl; + URIUtils::resolveHref(aUri, aBaseUri, absUrl); + + PRInt32 hash = absUrl.RFindChar(PRUnichar('#')); + PRUint32 urlEnd, fragStart, fragEnd; + if (hash == kNotFound) { + urlEnd = absUrl.Length(); + fragStart = 0; + fragEnd = 0; + } + else { + urlEnd = hash; + fragStart = hash + 1; + fragEnd = absUrl.Length(); + } + + nsDependentSubstring docUrl(absUrl, 0, urlEnd); + nsDependentSubstring frag(absUrl, fragStart, fragEnd); + + const txXPathNode* loadNode = aExecutionState->retrieveDocument(docUrl); + if (loadNode) { + if (frag.IsEmpty()) { + aNodeSet->add(*loadNode); + } + else { + txXPathTreeWalker walker(*loadNode); + if (walker.moveToElementById(frag)) { + aNodeSet->add(walker.getCurrentPosition()); + } + } + } +} + /* * Evaluates this Expr based on the given context node and processor state * NOTE: the implementation is incomplete since it does not make use of the @@ -97,7 +134,7 @@ DocumentFunctionCall::evaluate(txIEvalContext* aContext, baseURISet = MB_TRUE; if (!nodeSet2->isEmpty()) { - nodeSet2->get(0)->getBaseURI(baseURI); + txXPathNodeUtils::getBaseURI(nodeSet2->get(0), baseURI); } } @@ -108,18 +145,15 @@ DocumentFunctionCall::evaluate(txIEvalContext* aContext, exprResult1)); PRInt32 i; for (i = 0; i < nodeSet1->size(); ++i) { - Node* node = nodeSet1->get(i); + const txXPathNode& node = nodeSet1->get(i); nsAutoString uriStr; - XMLDOMUtils::getNodeValue(node, uriStr); + txXPathNodeUtils::appendNodeValue(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); + txXPathNodeUtils::getBaseURI(node, baseURI); } + retrieveNode(es, uriStr, baseURI, nodeSet); } NS_ADDREF(*aResult = nodeSet); @@ -130,11 +164,8 @@ DocumentFunctionCall::evaluate(txIEvalContext* aContext, // 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); - } + const nsAString* base = baseURISet ? &baseURI : &mBaseURI; + retrieveNode(es, uriStr, *base, nodeSet); NS_ADDREF(*aResult = nodeSet); diff --git a/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp index fa743d1de70..0b668a459bb 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp @@ -22,22 +22,16 @@ * */ +#include "ExprResult.h" #include "txAtoms.h" #include "txIXPathContext.h" -#include "XSLTFunctions.h" -#include "prprf.h" #include "txNodeSet.h" +#include "XSLTFunctions.h" /* Implementation of XSLT 1.0 extension function: generate-id */ -#ifndef HAVE_64BIT_OS -const char GenerateIdFunctionCall::printfFmt[] = "id0x%08p"; -#else -const char GenerateIdFunctionCall::printfFmt[] = "id0x%016p"; -#endif - /** * Creates a new generate-id function call **/ @@ -61,43 +55,41 @@ GenerateIdFunctionCall::evaluate(txIEvalContext* aContext, if (!requireParams(0, 1, aContext)) return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; - Node* node = 0; - - // get node to generate id for - if (params.getLength() == 1) { - txListIterator iter(¶ms); - Expr* param = (Expr*)iter.next(); - - nsRefPtr exprResult; - nsresult rv = param->evaluate(aContext, getter_AddRefs(exprResult)); + nsresult rv = NS_OK; + if (params.getLength() != 1) { + StringResult* strRes; + rv = aContext->recycler()->getStringResult(&strRes); NS_ENSURE_SUCCESS(rv, rv); - if (exprResult->getResultType() != txAExprResult::NODESET) { - NS_NAMED_LITERAL_STRING(err, "Invalid argument passed to generate-id(), expecting NodeSet"); - aContext->receiveError(err, NS_ERROR_XSLT_NODESET_EXPECTED); - return NS_ERROR_XSLT_NODESET_EXPECTED; - } + txXPathNodeUtils::getXSLTId(aContext->getContextNode(), + strRes->mValue); - txNodeSet* nodes = NS_STATIC_CAST(txNodeSet*, - NS_STATIC_CAST(txAExprResult*, - exprResult)); - if (nodes->isEmpty()) { - aContext->recycler()->getEmptyStringResult(aResult); - - return NS_OK; - } - - node = nodes->get(0); - } - else { - node = aContext->getContextNode(); + *aResult = strRes; + + return NS_OK; } - // generate id for selected node - char buf[22]; - PR_snprintf(buf, 21, printfFmt, node); - return aContext->recycler()->getStringResult(NS_ConvertASCIItoUCS2(buf), - aResult); + txListIterator iter(¶ms); + nsRefPtr nodes; + rv = evaluateToNodeSet(NS_STATIC_CAST(Expr*, iter.next()), aContext, + getter_AddRefs(nodes)); + NS_ENSURE_SUCCESS(rv, rv); + + if (nodes->isEmpty()) { + aContext->recycler()->getEmptyStringResult(aResult); + + return NS_OK; + } + + StringResult* strRes; + rv = aContext->recycler()->getStringResult(&strRes); + NS_ENSURE_SUCCESS(rv, rv); + + txXPathNodeUtils::getXSLTId(nodes->get(0), strRes->mValue); + + *aResult = strRes; + + return NS_OK; } nsresult GenerateIdFunctionCall::getNameAtom(nsIAtom** aAtom) diff --git a/mozilla/extensions/transformiix/source/xslt/functions/Makefile.in b/mozilla/extensions/transformiix/source/xslt/functions/Makefile.in index bc2d64e0c53..858aa643cbd 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/Makefile.in +++ b/mozilla/extensions/transformiix/source/xslt/functions/Makefile.in @@ -35,6 +35,7 @@ REQUIRES += dom \ content \ widget \ unicharutil \ + necko \ $(NULL) endif diff --git a/mozilla/extensions/transformiix/source/xslt/functions/XSLTFunctions.h b/mozilla/extensions/transformiix/source/xslt/functions/XSLTFunctions.h index 7ae1d5925e9..6f9c5fb481e 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/XSLTFunctions.h +++ b/mozilla/extensions/transformiix/source/xslt/functions/XSLTFunctions.h @@ -179,9 +179,6 @@ public: GenerateIdFunctionCall(); TX_DECL_FUNCTION; - -private: - static const char printfFmt[]; }; /** diff --git a/mozilla/extensions/transformiix/source/xslt/functions/txKey.h b/mozilla/extensions/transformiix/source/xslt/functions/txKey.h index a1c1d61e107..36baf250b7f 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/txKey.h +++ b/mozilla/extensions/transformiix/source/xslt/functions/txKey.h @@ -53,17 +53,17 @@ class txKeyValueHashKey { public: txKeyValueHashKey(const txExpandedName& aKeyName, - Document* aDocument, + PRInt32 aDocumentIdentifier, const nsAString& aKeyValue) : mKeyName(aKeyName), mKeyValue(aKeyValue), - mDocument(aDocument) + mDocumentIdentifier(aDocumentIdentifier) { } txExpandedName mKeyName; nsString mKeyValue; - Document* mDocument; + PRInt32 mDocumentIdentifier; }; struct txKeyValueHashEntry : public PLDHashEntryHdr @@ -89,14 +89,14 @@ class txIndexedKeyHashKey { public: txIndexedKeyHashKey(txExpandedName aKeyName, - Document* aDocument) + PRInt32 aDocumentIdentifier) : mKeyName(aKeyName), - mDocument(aDocument) + mDocumentIdentifier(aDocumentIdentifier) { } txExpandedName mKeyName; - Document* mDocument; + PRInt32 mDocumentIdentifier; }; struct txIndexedKeyHashEntry : public PLDHashEntryHdr @@ -145,7 +145,7 @@ public: * @param aKeyValueHash Hash to add values to * @param aEs txExecutionState to use for XPath evaluation */ - nsresult indexDocument(Document* aDocument, + nsresult indexDocument(const txXPathNode& aDocument, txKeyValueHash& aKeyValueHash, txExecutionState& aEs); @@ -158,7 +158,7 @@ private: * @param aKeyValueHash Hash to add values to * @param aEs txExecutionState to use for XPath evaluation */ - nsresult indexTree(Node* aNode, txKeyValueHashKey& aKey, + nsresult indexTree(const txXPathNode& aNode, txKeyValueHashKey& aKey, txKeyValueHash& aKeyValueHash, txExecutionState& aEs); /** @@ -169,7 +169,7 @@ private: * @param aKeyValueHash Hash to add values to * @param aEs txExecutionState to use for XPath evaluation */ - nsresult testNode(Node* aNode, txKeyValueHashKey& aKey, + nsresult testNode(const txXPathNode& aNode, txKeyValueHashKey& aKey, txKeyValueHash& aKeyValueHash, txExecutionState& aEs); /** @@ -203,7 +203,7 @@ public: nsresult init(); nsresult getKeyNodes(const txExpandedName& aKeyName, - Document* aDocument, + const txXPathNode& aDocument, const nsAString& aKeyValue, PRBool aIndexIfNotFound, txExecutionState& aEs, diff --git a/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp index a211e963f4d..855780d5466 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp @@ -21,7 +21,6 @@ #include "txExecutionState.h" #include "txAtoms.h" #include "txSingleNodeContext.h" -#include "XMLDOMUtils.h" #include "XSLTFunctions.h" #include "nsReadableUtils.h" #include "txKey.h" @@ -70,12 +69,8 @@ txKeyFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) rv = ((Expr*)iter.next())->evaluate(aContext, getter_AddRefs(exprResult)); NS_ENSURE_SUCCESS(rv, rv); - Document* contextDoc; - Node* contextNode = aContext->getContextNode(); - if (contextNode->getNodeType() == Node::DOCUMENT_NODE) - contextDoc = (Document*)contextNode; - else - contextDoc = contextNode->getOwnerDocument(); + nsAutoPtr contextDoc(txXPathNodeUtils::getOwnerDocument(aContext->getContextNode())); + NS_ENSURE_TRUE(contextDoc, NS_ERROR_FAILURE); nsRefPtr res; txNodeSet* nodeSet; @@ -89,20 +84,20 @@ txKeyFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) PRInt32 i; for (i = 0; i < nodeSet->size(); ++i) { nsAutoString val; - XMLDOMUtils::getNodeValue(nodeSet->get(i), val); + txXPathNodeUtils::appendNodeValue(nodeSet->get(i), val); nsRefPtr nodes; - rv = es->getKeyNodes(keyName, contextDoc, val, i == 0, + rv = es->getKeyNodes(keyName, *contextDoc, val, i == 0, getter_AddRefs(nodes)); NS_ENSURE_SUCCESS(rv, rv); - res->add(nodes); + res->add(*nodes); } } else { nsAutoString val; exprResult->stringValue(val); - rv = es->getKeyNodes(keyName, contextDoc, val, PR_TRUE, + rv = es->getKeyNodes(keyName, *contextDoc, val, PR_TRUE, getter_AddRefs(res)); NS_ENSURE_SUCCESS(rv, rv); } @@ -140,7 +135,7 @@ txKeyValueHashEntry::MatchEntry(const void* aKey) const NS_STATIC_CAST(const txKeyValueHashKey*, aKey); return mKey.mKeyName == key->mKeyName && - mKey.mDocument == key->mDocument && + mKey.mDocumentIdentifier == key->mDocumentIdentifier && mKey.mKeyValue.Equals(key->mKeyValue); } @@ -152,7 +147,7 @@ txKeyValueHashEntry::HashKey(const void* aKey) return key->mKeyName.mNamespaceID ^ NS_PTR_TO_INT32(key->mKeyName.mLocalName.get()) ^ - NS_PTR_TO_INT32(key->mDocument) ^ + key->mDocumentIdentifier ^ HashString(key->mKeyValue); } @@ -169,7 +164,7 @@ txIndexedKeyHashEntry::MatchEntry(const void* aKey) const NS_STATIC_CAST(const txIndexedKeyHashKey*, aKey); return mKey.mKeyName == key->mKeyName && - mKey.mDocument == key->mDocument; + mKey.mDocumentIdentifier == key->mDocumentIdentifier; } PLDHashNumber @@ -180,7 +175,7 @@ txIndexedKeyHashEntry::HashKey(const void* aKey) return key->mKeyName.mNamespaceID ^ NS_PTR_TO_INT32(key->mKeyName.mLocalName.get()) ^ - NS_PTR_TO_INT32(key->mDocument); + key->mDocumentIdentifier; } /* @@ -189,7 +184,7 @@ txIndexedKeyHashEntry::HashKey(const void* aKey) nsresult txKeyHash::getKeyNodes(const txExpandedName& aKeyName, - Document* aDocument, + const txXPathNode& aDocument, const nsAString& aKeyValue, PRBool aIndexIfNotFound, txExecutionState& aEs, @@ -199,7 +194,10 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName, NS_ERROR_OUT_OF_MEMORY); *aResult = nsnull; - txKeyValueHashKey valueKey(aKeyName, aDocument, aKeyValue); + + PRInt32 identifier = txXPathNodeUtils::getUniqueIdentifier(aDocument); + + txKeyValueHashKey valueKey(aKeyName, identifier, aKeyValue); txKeyValueHashEntry* valueEntry = mKeyValues.GetEntry(valueKey); if (valueEntry) { *aResult = valueEntry->mNodeSet; @@ -221,7 +219,7 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName, return NS_OK; } - txIndexedKeyHashKey indexKey(aKeyName, aDocument); + txIndexedKeyHashKey indexKey(aKeyName, identifier); txIndexedKeyHashEntry* indexEntry = mIndexedKeys.AddEntry(indexKey); NS_ENSURE_TRUE(indexEntry, NS_ERROR_OUT_OF_MEMORY); @@ -230,6 +228,7 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName, // return the empty nodeset. *aResult = mEmptyNodeSet; NS_ADDREF(*aResult); + return NS_OK; } @@ -318,11 +317,13 @@ PRBool txXSLKey::addKey(nsAutoPtr aMatch, nsAutoPtr aUse) * @param aKeyValueHash Hash to add values to * @param aEs txExecutionState to use for XPath evaluation */ -nsresult txXSLKey::indexDocument(Document* aDocument, +nsresult txXSLKey::indexDocument(const txXPathNode& aDocument, txKeyValueHash& aKeyValueHash, txExecutionState& aEs) { - txKeyValueHashKey key(mName, aDocument, NS_LITERAL_STRING("")); + txKeyValueHashKey key(mName, + txXPathNodeUtils::getUniqueIdentifier(aDocument), + NS_LITERAL_STRING("")); return indexTree(aDocument, key, aKeyValueHash, aEs); } @@ -334,30 +335,34 @@ nsresult txXSLKey::indexDocument(Document* aDocument, * @param aKeyValueHash Hash to add values to * @param aEs txExecutionState to use for XPath evaluation */ -nsresult txXSLKey::indexTree(Node* aNode, txKeyValueHashKey& aKey, +nsresult txXSLKey::indexTree(const txXPathNode& aNode, + txKeyValueHashKey& aKey, txKeyValueHash& aKeyValueHash, txExecutionState& aEs) { nsresult rv = testNode(aNode, aKey, aKeyValueHash, aEs); NS_ENSURE_SUCCESS(rv, rv); - // check if the nodes attributes matches - NamedNodeMap* attrs = aNode->getAttributes(); - if (attrs) { - for (PRUint32 i=0; igetLength(); i++) { - rv = testNode(attrs->item(i), aKey, aKeyValueHash, aEs); + // check if the node's attributes match + txXPathTreeWalker walker(aNode); + if (walker.moveToFirstAttribute()) { + do { + rv = testNode(walker.getCurrentPosition(), aKey, aKeyValueHash, + aEs); NS_ENSURE_SUCCESS(rv, rv); - } + } while (walker.moveToNextAttribute()); + walker.moveToParent(); } - Node* child = aNode->getFirstChild(); - while (child) { - rv = indexTree(child, aKey, aKeyValueHash, aEs); - NS_ENSURE_SUCCESS(rv, rv); - - child = child->getNextSibling(); + // check if the node's descendants match + if (walker.moveToFirstChild()) { + do { + rv = indexTree(walker.getCurrentPosition(), aKey, aKeyValueHash, + aEs); + NS_ENSURE_SUCCESS(rv, rv); + } while (walker.moveToNextSibling()); } - + return NS_OK; } @@ -369,7 +374,7 @@ nsresult txXSLKey::indexTree(Node* aNode, txKeyValueHashKey& aKey, * @param aKeyValueHash Hash to add values to * @param aEs txExecutionState to use for XPath evaluation */ -nsresult txXSLKey::testNode(Node* aNode, +nsresult txXSLKey::testNode(const txXPathNode& aNode, txKeyValueHashKey& aKey, txKeyValueHash& aKeyValueHash, txExecutionState& aEs) @@ -398,7 +403,7 @@ nsresult txXSLKey::testNode(Node* aNode, PRInt32 i; for (i = 0; i < res->size(); ++i) { val.Truncate(); - XMLDOMUtils::getNodeValue(res->get(i), val); + txXPathNodeUtils::appendNodeValue(res->get(i), val); aKey.mKeyValue.Assign(val); txKeyValueHashEntry* entry = aKeyValueHash.AddEntry(aKey); diff --git a/mozilla/extensions/transformiix/source/xslt/txExecutionState.cpp b/mozilla/extensions/transformiix/source/xslt/txExecutionState.cpp index fcaf2c559a7..0e68e6b4103 100644 --- a/mozilla/extensions/transformiix/source/xslt/txExecutionState.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txExecutionState.cpp @@ -53,53 +53,41 @@ const PRInt32 txExecutionState::kMaxRecursionDepth = 20000; -DHASH_WRAPPER(txLoadedDocumentsBase, txLoadedDocumentEntry, nsAString&) - -nsresult txLoadedDocumentsHash::init(Document* aSourceDocument) +nsresult txLoadedDocumentsHash::init(txXPathNode* aSourceDocument) { nsresult rv = Init(8); NS_ENSURE_SUCCESS(rv, rv); mSourceDocument = aSourceDocument; - Add(mSourceDocument); + + nsAutoString baseURI; + txXPathNodeUtils::getBaseURI(*mSourceDocument, baseURI); + + txLoadedDocumentEntry* entry = PutEntry(baseURI); + if (!entry) { + return NS_ERROR_FAILURE; + } + + entry->mDocument = mSourceDocument; return NS_OK; } txLoadedDocumentsHash::~txLoadedDocumentsHash() { - if (!mHashTable.ops) { + if (!IsInitialized()) { return; } nsAutoString baseURI; - mSourceDocument->getBaseURI(baseURI); + txXPathNodeUtils::getBaseURI(*mSourceDocument, baseURI); + txLoadedDocumentEntry* entry = GetEntry(baseURI); if (entry) { - entry->mDocument = nsnull; + delete entry->mDocument.forget(); } } -void txLoadedDocumentsHash::Add(Document* aDocument) -{ - nsAutoString baseURI; - aDocument->getBaseURI(baseURI); - txLoadedDocumentEntry* entry = AddEntry(baseURI); - if (entry) { - entry->mDocument = aDocument; - } -} - -Document* txLoadedDocumentsHash::Get(const nsAString& aURI) -{ - txLoadedDocumentEntry* entry = GetEntry(aURI); - if (entry) { - return entry->mDocument; - } - - return nsnull; -} - txExecutionState::txExecutionState(txStylesheet* aStylesheet) : mStylesheet(aStylesheet), mNextInstruction(nsnull), @@ -110,7 +98,7 @@ txExecutionState::txExecutionState(txStylesheet* aStylesheet) mTemplateRuleCount(0), mEvalContext(nsnull), mInitialEvalContext(nsnull), - mRTFDocument(nsnull), +// mRTFDocument(nsnull), mGlobalParams(nsnull), mKeyHash(aStylesheet->getKeyMap()) { @@ -121,7 +109,7 @@ txExecutionState::~txExecutionState() delete mResultHandler; delete mLocalVariables; delete mEvalContext; - delete mRTFDocument; +// delete mRTFDocument; PRInt32 i; for (i = 0; i < mTemplateRuleCount; ++i) { @@ -154,7 +142,7 @@ txExecutionState::~txExecutionState() } nsresult -txExecutionState::init(Node* aNode, +txExecutionState::init(const txXPathNode& aNode, txExpandedNameMap* aGlobalParams) { nsresult rv = NS_OK; @@ -178,16 +166,15 @@ txExecutionState::init(Node* aNode, mOutputHandler->startDocument(); // Set up loaded-documents-hash - Document* sourceDoc; - if (aNode->getNodeType() == Node::DOCUMENT_NODE) { - sourceDoc = (Document*)aNode; - } - else { - sourceDoc = aNode->getOwnerDocument(); - } - rv = mLoadedDocuments.init(sourceDoc); + nsAutoPtr document(txXPathNodeUtils::getOwnerDocument(aNode)); + NS_ENSURE_TRUE(document, NS_ERROR_FAILURE); + + rv = mLoadedDocuments.init(document); NS_ENSURE_SUCCESS(rv, rv); + // loaded-documents-hash owns this now + document.forget(); + // Init members rv = mKeyHash.init(); NS_ENSURE_SUCCESS(rv, rv); @@ -338,7 +325,7 @@ txExecutionState::getVariable(PRInt32 aNamespace, nsIAtom* aLName, } PRBool -txExecutionState::isStripSpaceAllowed(Node* aNode) +txExecutionState::isStripSpaceAllowed(const txXPathNode& aNode) { return mStylesheet->isStripSpaceAllowed(aNode, this); } @@ -474,70 +461,47 @@ txExecutionState::getEvalContext() return mEvalContext; } -Node* -txExecutionState::retrieveDocument(const nsAString& uri, - const nsAString& baseUri) +const txXPathNode* +txExecutionState::retrieveDocument(const nsAString& aUri) { - nsAutoString absUrl; - URIUtils::resolveHref(uri, baseUri, absUrl); - - PRInt32 hash = absUrl.RFindChar(PRUnichar('#')); - PRUint32 urlEnd, fragStart, fragEnd; - if (hash == kNotFound) { - urlEnd = absUrl.Length(); - fragStart = 0; - fragEnd = 0; - } - else { - urlEnd = hash; - fragStart = hash + 1; - fragEnd = absUrl.Length(); - } - - nsDependentSubstring docUrl(absUrl, 0, urlEnd); - nsDependentSubstring frag(absUrl, fragStart, fragEnd); + NS_ASSERTION(aUri.FindChar(PRUnichar('#')) == kNotFound, + "Remove the fragment."); PR_LOG(txLog::xslt, PR_LOG_DEBUG, - ("Retrieve Document %s, uri %s, baseUri %s, fragment %s\n", - NS_LossyConvertUCS2toASCII(docUrl).get(), - NS_LossyConvertUCS2toASCII(uri).get(), - NS_LossyConvertUCS2toASCII(baseUri).get(), - NS_LossyConvertUCS2toASCII(frag).get())); + ("Retrieve Document %s", NS_LossyConvertUCS2toASCII(aUri).get())); // try to get already loaded document - Document* xmlDoc = mLoadedDocuments.Get(docUrl); + txLoadedDocumentEntry *entry = mLoadedDocuments.PutEntry(aUri); + if (!entry) { + return nsnull; + } - if (!xmlDoc) { + if (!entry->mDocument) { // open URI nsAutoString errMsg, refUri; // XXX we should get the referrer from the actual node // triggering the load, but this will do for the time being - mLoadedDocuments.mSourceDocument->getBaseURI(refUri); + txXPathNodeUtils::getBaseURI(*mLoadedDocuments.mSourceDocument, refUri); nsresult rv; - rv = txParseDocumentFromURI(docUrl, refUri, - mLoadedDocuments.mSourceDocument, errMsg, - &xmlDoc); + rv = txParseDocumentFromURI(aUri, refUri, + *mLoadedDocuments.mSourceDocument, errMsg, + getter_Transfers(entry->mDocument)); - if (NS_FAILED(rv) || !xmlDoc) { + if (NS_FAILED(rv) || !entry->mDocument) { + mLoadedDocuments.RawRemoveEntry(entry); receiveError(NS_LITERAL_STRING("Couldn't load document '") + - docUrl + NS_LITERAL_STRING("': ") + errMsg, rv); + aUri + NS_LITERAL_STRING("': ") + errMsg, rv); + return nsnull; } - // add to list of documents - mLoadedDocuments.Add(xmlDoc); } - // return element with supplied id if supplied - if (!frag.IsEmpty()) { - return xmlDoc->getElementById(frag); - } - - return xmlDoc; + return entry->mDocument; } nsresult txExecutionState::getKeyNodes(const txExpandedName& aKeyName, - Document* aDocument, + const txXPathNode& aDocument, const nsAString& aKeyValue, PRBool aIndexIfNotFound, txNodeSet** aResult) diff --git a/mozilla/extensions/transformiix/source/xslt/txExecutionState.h b/mozilla/extensions/transformiix/source/xslt/txExecutionState.h index 97a27594b60..e25044f1289 100644 --- a/mozilla/extensions/transformiix/source/xslt/txExecutionState.h +++ b/mozilla/extensions/transformiix/source/xslt/txExecutionState.h @@ -47,7 +47,8 @@ #include "nsVoidArray.h" #include "txIXPathContext.h" #include "txVariableMap.h" -#include "nsDoubleHashtable.h" +#include "nsTHashtable.h" +#include "nsHashKeys.h" #include "txKey.h" #include "txStylesheet.h" @@ -55,32 +56,36 @@ class txInstruction; class txIOutputHandlerFactory; class txExpandedNameMap; -class txLoadedDocumentEntry : public PLDHashStringEntry +class txLoadedDocumentEntry : public nsStringHashKey { public: - txLoadedDocumentEntry(const void* aKey) : PLDHashStringEntry(aKey) + txLoadedDocumentEntry(KeyTypePointer aStr) : nsStringHashKey(aStr) { } + txLoadedDocumentEntry(const txLoadedDocumentEntry& aToCopy) + : nsStringHashKey(aToCopy) + { + NS_ERROR("We're horked."); + } ~txLoadedDocumentEntry() { - delete mDocument; + if (mDocument) { + txXPathNodeUtils::release(mDocument); + } } - Document* mDocument; + + nsAutoPtr mDocument; }; -DECL_DHASH_WRAPPER(txLoadedDocumentsBase, txLoadedDocumentEntry, nsAString&) - -class txLoadedDocumentsHash : public txLoadedDocumentsBase +class txLoadedDocumentsHash : public nsTHashtable { public: ~txLoadedDocumentsHash(); - nsresult init(Document* aSourceDocument); - void Add(Document* aDocument); - Document* Get(const nsAString& aURI); + nsresult init(txXPathNode* aSourceDocument); private: friend class txExecutionState; - Document* mSourceDocument; + txXPathNode* mSourceDocument; }; @@ -89,7 +94,7 @@ class txExecutionState : public txIMatchContext public: txExecutionState(txStylesheet* aStylesheet); ~txExecutionState(); - nsresult init(Node* aNode, txExpandedNameMap* aGlobalParams); + nsresult init(const txXPathNode& aNode, txExpandedNameMap* aGlobalParams); nsresult end(); TX_DECL_MATCH_CONTEXT; @@ -123,8 +128,9 @@ public: // state-getting functions txIEvalContext* getEvalContext(); txExpandedNameMap* getParamMap(); - Node* retrieveDocument(const nsAString& uri, const nsAString& baseUri); - nsresult getKeyNodes(const txExpandedName& aKeyName, Document* aDocument, + const txXPathNode* retrieveDocument(const nsAString& aUri); + nsresult getKeyNodes(const txExpandedName& aKeyName, + const txXPathNode& aDocument, const nsAString& aKeyValue, PRBool aIndexIfNotFound, txNodeSet** aResult); TemplateRule* getCurrentTemplateRule(); @@ -168,7 +174,7 @@ private: txIEvalContext* mEvalContext; txIEvalContext* mInitialEvalContext; - Document* mRTFDocument; + //Document* mRTFDocument; txExpandedNameMap* mGlobalParams; txLoadedDocumentsHash mLoadedDocuments; diff --git a/mozilla/extensions/transformiix/source/xslt/txInstructions.cpp b/mozilla/extensions/transformiix/source/xslt/txInstructions.cpp index cc70f4c7b47..fa73a859dc8 100644 --- a/mozilla/extensions/transformiix/source/xslt/txInstructions.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txInstructions.cpp @@ -278,84 +278,82 @@ txComment::execute(txExecutionState& aEs) } nsresult -txCopyBase::copyNode(Node* aNode, txExecutionState& aEs) +txCopyBase::copyNode(const txXPathNode& aNode, txExecutionState& aEs) { - NS_ASSERTION(aNode, "missing node to copy"); - switch (aNode->getNodeType()) { - case Node::ATTRIBUTE_NODE: + switch (txXPathNodeUtils::getNodeType(aNode)) { + case txXPathNodeType::ATTRIBUTE_NODE: { nsAutoString nodeName, nodeValue; - aNode->getNodeName(nodeName); - aNode->getNodeValue(nodeValue); + txXPathNodeUtils::getNodeName(aNode, nodeName); + txXPathNodeUtils::appendNodeValue(aNode, nodeValue); aEs.mResultHandler->attribute(nodeName, - aNode->getNamespaceID(), + txXPathNodeUtils::getNamespaceID(aNode), nodeValue); break; } - case Node::COMMENT_NODE: + case txXPathNodeType::COMMENT_NODE: { nsAutoString nodeValue; - aNode->getNodeValue(nodeValue); + txXPathNodeUtils::appendNodeValue(aNode, nodeValue); aEs.mResultHandler->comment(nodeValue); break; } - case Node::DOCUMENT_NODE: - case Node::DOCUMENT_FRAGMENT_NODE: + case txXPathNodeType::DOCUMENT_NODE: + case txXPathNodeType::DOCUMENT_FRAGMENT_NODE: { // Copy children - Node* child = aNode->getFirstChild(); - while (child) { - copyNode(child, aEs); - child = child->getNextSibling(); + txXPathTreeWalker walker(aNode); + PRBool hasChild = walker.moveToFirstChild(); + while (hasChild) { + copyNode(walker.getCurrentPosition(), aEs); + hasChild = walker.moveToNextSibling(); } break; } - case Node::ELEMENT_NODE: + case txXPathNodeType::ELEMENT_NODE: { - Element* element = NS_STATIC_CAST(Element*, aNode); nsAutoString name; - element->getNodeName(name); - PRInt32 nsID = element->getNamespaceID(); + txXPathNodeUtils::getNodeName(aNode, name); + PRInt32 nsID = txXPathNodeUtils::getNamespaceID(aNode); aEs.mResultHandler->startElement(name, nsID); // Copy attributes - NamedNodeMap* attList = element->getAttributes(); - if (attList) { - PRUint32 i = 0; - for (i = 0; i < attList->getLength(); i++) { - Attr* attr = NS_STATIC_CAST(Attr*, attList->item(i)); + txXPathTreeWalker walker(aNode); + if (walker.moveToFirstAttribute()) { + do { nsAutoString nodeName, nodeValue; - attr->getNodeName(nodeName); - attr->getNodeValue(nodeValue); + walker.getNodeName(nodeName); + walker.appendNodeValue(nodeValue); aEs.mResultHandler->attribute(nodeName, - attr->getNamespaceID(), + walker.getNamespaceID(), nodeValue); - } + } while (walker.moveToNextAttribute()); + walker.moveToParent(); } // Copy children - Node* child = element->getFirstChild(); - while (child) { - copyNode(child, aEs); - child = child->getNextSibling(); + PRBool hasChild = walker.moveToFirstChild(); + while (hasChild) { + copyNode(walker.getCurrentPosition(), aEs); + hasChild = walker.moveToNextSibling(); } aEs.mResultHandler->endElement(name, nsID); break; } - case Node::PROCESSING_INSTRUCTION_NODE: + case txXPathNodeType::PROCESSING_INSTRUCTION_NODE: { nsAutoString target, data; - aNode->getNodeName(target); - aNode->getNodeValue(data); + txXPathNodeUtils::getNodeName(aNode, target); + txXPathNodeUtils::appendNodeValue(aNode, data); aEs.mResultHandler->processingInstruction(target, data); break; } - case Node::TEXT_NODE: - case Node::CDATA_SECTION_NODE: + case txXPathNodeType::TEXT_NODE: + case txXPathNodeType::CDATA_SECTION_NODE: { nsAutoString nodeValue; - aNode->getNodeValue(nodeValue); + txXPathNodeUtils::appendNodeValue(aNode, nodeValue); aEs.mResultHandler->characters(nodeValue, PR_FALSE); break; } @@ -373,10 +371,10 @@ nsresult txCopy::execute(txExecutionState& aEs) { nsresult rv = NS_OK; - Node* node = aEs.getEvalContext()->getContextNode(); + const txXPathNode& node = aEs.getEvalContext()->getContextNode(); - switch (node->getNodeType()) { - case Node::DOCUMENT_NODE: + switch (txXPathNodeUtils::getNodeType(node)) { + case txXPathNodeType::DOCUMENT_NODE: { // "close" current element to ensure that no attributes are added aEs.mResultHandler->characters(NS_LITERAL_STRING(""), PR_FALSE); @@ -389,11 +387,11 @@ txCopy::execute(txExecutionState& aEs) break; } - case Node::ELEMENT_NODE: + case txXPathNodeType::ELEMENT_NODE: { nsAutoString nodeName; - node->getNodeName(nodeName); - PRInt32 nsID = node->getNamespaceID(); + txXPathNodeUtils::getNodeName(node, nodeName); + PRInt32 nsID = txXPathNodeUtils::getNamespaceID(node); aEs.mResultHandler->startElement(nodeName, nsID); // XXX copy namespace nodes once we have them diff --git a/mozilla/extensions/transformiix/source/xslt/txInstructions.h b/mozilla/extensions/transformiix/source/xslt/txInstructions.h index 6e127fbaa69..6f49699683c 100644 --- a/mozilla/extensions/transformiix/source/xslt/txInstructions.h +++ b/mozilla/extensions/transformiix/source/xslt/txInstructions.h @@ -154,7 +154,7 @@ public: class txCopyBase : public txInstruction { protected: - nsresult copyNode(Node* aNode, txExecutionState& aEs); + nsresult copyNode(const txXPathNode& aNode, txExecutionState& aEs); }; class txCopy : public txCopyBase diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaStylesheetCompiler.cpp b/mozilla/extensions/transformiix/source/xslt/txMozillaStylesheetCompiler.cpp index b886cce77e8..15a6afb179c 100644 --- a/mozilla/extensions/transformiix/source/xslt/txMozillaStylesheetCompiler.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaStylesheetCompiler.cpp @@ -630,7 +630,7 @@ handleNode(nsIDOMNode* aNode, txStylesheetCompiler* aCompiler) { nsCOMPtr document = do_QueryInterface(aNode); - PRInt32 counter = 0; + PRUint32 counter = 0; nsIContent *child; while ((child = document->GetChildAt(counter++))) { nsCOMPtr childNode = do_QueryInterface(child); diff --git a/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp index e21a56fbd45..e404616b3a1 100644 --- a/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txMozillaXSLTProcessor.cpp @@ -57,7 +57,6 @@ #include "txExecutionState.h" #include "txMozillaTextOutput.h" #include "txMozillaXMLOutput.h" -#include "txSingleNodeContext.h" #include "txURIUtils.h" #include "XMLUtils.h" #include "txUnknownHandler.h" @@ -290,24 +289,27 @@ txMozillaXSLTProcessor::TransformDocument(nsIDOMNode* aSourceDOM, nsresult rv = TX_CompileStylesheet(aStyleDOM, getter_AddRefs(mStylesheet)); NS_ENSURE_SUCCESS(rv, rv); - // Create wrapper for the source document. + mSource = aSourceDOM; - nsCOMPtr sourceDOMDocument; - mSource->GetOwnerDocument(getter_AddRefs(sourceDOMDocument)); - if (!sourceDOMDocument) { - sourceDOMDocument = do_QueryInterface(mSource); + + nsAutoPtr sourceNode(txXPathNativeNode::createXPathNode(aSourceDOM)); + if (!sourceNode) { + return NS_ERROR_OUT_OF_MEMORY; + } + + nsCOMPtr sourceDOMDocument; + aSourceDOM->GetOwnerDocument(getter_AddRefs(sourceDOMDocument)); + if (!sourceDOMDocument) { + sourceDOMDocument = do_QueryInterface(aSourceDOM); } - NS_ENSURE_TRUE(sourceDOMDocument, NS_ERROR_FAILURE); - Document sourceDocument(sourceDOMDocument); - Node* sourceNode = sourceDocument.createWrapper(mSource); - NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE); txExecutionState es(mStylesheet); + txToDocHandlerFactory handlerFactory(&es, sourceDOMDocument, aOutputDoc, nsnull); es.mOutputHandlerFactory = &handlerFactory; - es.init(sourceNode, &mVariables); + es.init(*sourceNode, &mVariables); // Process root of XML source document rv = txXSLTProcessor::execute(es); @@ -348,16 +350,16 @@ txMozillaXSLTProcessor::DoTransform() NS_ENSURE_TRUE(mStylesheet, NS_ERROR_UNEXPECTED); NS_ASSERTION(mObserver, "no observer"); - // Create wrapper for the source document. + nsAutoPtr sourceNode(txXPathNativeNode::createXPathNode(mSource)); + if (!sourceNode) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsCOMPtr sourceDOMDocument; mSource->GetOwnerDocument(getter_AddRefs(sourceDOMDocument)); if (!sourceDOMDocument) { sourceDOMDocument = do_QueryInterface(mSource); } - NS_ENSURE_TRUE(sourceDOMDocument, NS_ERROR_FAILURE); - Document sourceDocument(sourceDOMDocument); - Node* sourceNode = sourceDocument.createWrapper(mSource); - NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE); txExecutionState es(mStylesheet); @@ -367,7 +369,7 @@ txMozillaXSLTProcessor::DoTransform() mObserver); es.mOutputHandlerFactory = &handlerFactory; - es.init(sourceNode, &mVariables); + es.init(*sourceNode, &mVariables); // Process root of XML source document nsresult rv = txXSLTProcessor::execute(es); @@ -437,16 +439,16 @@ txMozillaXSLTProcessor::TransformToDocument(nsIDOMNode *aSource, nsresult rv = ensureStylesheet(); NS_ENSURE_SUCCESS(rv, rv); - // Create wrapper for the source document. + nsAutoPtr sourceNode(txXPathNativeNode::createXPathNode(aSource)); + if (!sourceNode) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsCOMPtr sourceDOMDocument; aSource->GetOwnerDocument(getter_AddRefs(sourceDOMDocument)); if (!sourceDOMDocument) { sourceDOMDocument = do_QueryInterface(aSource); } - NS_ENSURE_TRUE(sourceDOMDocument, NS_ERROR_FAILURE); - Document sourceDocument(sourceDOMDocument); - Node* sourceNode = sourceDocument.createWrapper(aSource); - NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE); txExecutionState es(mStylesheet); @@ -456,7 +458,7 @@ txMozillaXSLTProcessor::TransformToDocument(nsIDOMNode *aSource, nsnull); es.mOutputHandlerFactory = &handlerFactory; - es.init(sourceNode, &mVariables); + es.init(*sourceNode, &mVariables); // Process root of XML source document rv = txXSLTProcessor::execute(es); @@ -490,16 +492,10 @@ txMozillaXSLTProcessor::TransformToFragment(nsIDOMNode *aSource, nsresult rv = ensureStylesheet(); NS_ENSURE_SUCCESS(rv, rv); - // Create wrapper for the source document. - nsCOMPtr sourceDOMDocument; - aSource->GetOwnerDocument(getter_AddRefs(sourceDOMDocument)); - if (!sourceDOMDocument) { - sourceDOMDocument = do_QueryInterface(aSource); + nsAutoPtr sourceNode(txXPathNativeNode::createXPathNode(aSource)); + if (!sourceNode) { + return NS_ERROR_OUT_OF_MEMORY; } - NS_ENSURE_TRUE(sourceDOMDocument, NS_ERROR_FAILURE); - Document sourceDocument(sourceDOMDocument); - Node* sourceNode = sourceDocument.createWrapper(aSource); - NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE); txExecutionState es(mStylesheet); @@ -510,7 +506,7 @@ txMozillaXSLTProcessor::TransformToFragment(nsIDOMNode *aSource, txToFragmentHandlerFactory handlerFactory(*aResult); es.mOutputHandlerFactory = &handlerFactory; - es.init(sourceNode, &mVariables); + es.init(*sourceNode, &mVariables); // Process root of XML source document rv = txXSLTProcessor::execute(es); diff --git a/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp b/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp index 23d7d52badf..5fb17e25dc0 100644 --- a/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp @@ -317,11 +317,11 @@ nsresult txPatternParser::createStepPattern(txExprLexer& aLexer, } if (isAttr) { nodeTest = new txNameTest(prefix, lName, nspace, - Node::ATTRIBUTE_NODE); + txXPathNodeType::ATTRIBUTE_NODE); } else { nodeTest = new txNameTest(prefix, lName, nspace, - Node::ELEMENT_NODE); + txXPathNodeType::ELEMENT_NODE); } if (!nodeTest) { return NS_ERROR_OUT_OF_MEMORY; diff --git a/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.cpp b/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.cpp index 8bd3e243dd2..74fe4f22b6c 100644 --- a/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.cpp @@ -43,7 +43,6 @@ #include "nsCRT.h" #include "nsReadableUtils.h" #include "txHTMLOutput.h" -#include "txSingleNodeContext.h" #include "txTextOutput.h" #include "txUnknownHandler.h" #include "txURIUtils.h" @@ -127,13 +126,13 @@ nsresult txStandaloneXSLTProcessor::transform(nsACString& aXMLPath, ostream& aOut, ErrorObserver& aErr) { - Document* xmlDoc = parsePath(aXMLPath, aErr); + txXPathNode* xmlDoc = parsePath(aXMLPath, aErr); if (!xmlDoc) { return NS_ERROR_FAILURE; } // transform - nsresult rv = transform(xmlDoc, aOut, aErr); + nsresult rv = transform(*xmlDoc, aOut, aErr); delete xmlDoc; @@ -149,7 +148,7 @@ txStandaloneXSLTProcessor::transform(nsACString& aXMLPath, nsACString& aXSLPath, ostream& aOut, ErrorObserver& aErr) { - Document* xmlDoc = parsePath(aXMLPath, aErr); + txXPathNode* xmlDoc = parsePath(aXMLPath, aErr); if (!xmlDoc) { return NS_ERROR_FAILURE; } @@ -162,7 +161,7 @@ txStandaloneXSLTProcessor::transform(nsACString& aXMLPath, return rv; } // transform - rv = transform(xmlDoc, style, aOut, aErr); + rv = transform(*xmlDoc, style, aOut, aErr); delete xmlDoc; @@ -175,24 +174,24 @@ txStandaloneXSLTProcessor::transform(nsACString& aXMLPath, * or an error is returned. */ nsresult -txStandaloneXSLTProcessor::transform(Document* aXMLDoc, ostream& aOut, +txStandaloneXSLTProcessor::transform(txXPathNode& aXMLDoc, ostream& aOut, ErrorObserver& aErr) { - if (!aXMLDoc) { - return NS_ERROR_INVALID_POINTER; - } + Document* xmlDoc; + nsresult rv = txXPathNativeNode::getDocument(aXMLDoc, &xmlDoc); + NS_ENSURE_SUCCESS(rv, rv); // get stylesheet path nsAutoString stylePath, basePath; - aXMLDoc->getBaseURI(basePath); - getHrefFromStylesheetPI(*aXMLDoc, stylePath); + xmlDoc->getBaseURI(basePath); + getHrefFromStylesheetPI(*xmlDoc, stylePath); txParsedURL base, ref, resolved; base.init(basePath); ref.init(stylePath); base.resolve(ref, resolved); nsRefPtr style; - nsresult rv = TX_CompileStylesheetPath(resolved, getter_AddRefs(style)); + rv = TX_CompileStylesheetPath(resolved, getter_AddRefs(style)); NS_ENSURE_SUCCESS(rv, rv); // transform @@ -206,7 +205,7 @@ txStandaloneXSLTProcessor::transform(Document* aXMLDoc, ostream& aOut, * and prints the results to the given ostream argument */ nsresult -txStandaloneXSLTProcessor::transform(Document* aSource, +txStandaloneXSLTProcessor::transform(txXPathNode& aSource, txStylesheet* aStylesheet, ostream& aOut, ErrorObserver& aErr) { @@ -356,7 +355,7 @@ void txStandaloneXSLTProcessor::parseStylesheetPI(const nsAFlatString& aData, } } -Document* +txXPathNode* txStandaloneXSLTProcessor::parsePath(const nsACString& aPath, ErrorObserver& aErr) { NS_ConvertASCIItoUCS2 path(aPath); @@ -367,7 +366,7 @@ txStandaloneXSLTProcessor::parsePath(const nsACString& aPath, ErrorObserver& aEr return 0; } // parse source - Document* xmlDoc; + txXPathNode* xmlDoc; nsAutoString errors; nsresult rv = txParseFromStream(xmlInput, path, errors, &xmlDoc); xmlInput.close(); diff --git a/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.h b/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.h index bca42e91bbe..d460a93ca91 100644 --- a/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.h +++ b/mozilla/extensions/transformiix/source/xslt/txStandaloneXSLTProcessor.h @@ -122,7 +122,7 @@ public: * @param aErr error observer * @result NS_OK if transformation was successful */ - nsresult transform(Document* aXMLDoc, ostream& aOut, ErrorObserver& aErr); + nsresult transform(txXPathNode& aXMLDoc, ostream& aOut, ErrorObserver& aErr); /** * Transform a XML document with the given stylesheet. @@ -133,7 +133,7 @@ public: * @param aErr error observer * @result NS_OK if transformation was successful */ - nsresult transform(Document* aXMLDoc, txStylesheet* aXSLNode, + nsresult transform(txXPathNode& aXMLDoc, txStylesheet* aXSLNode, ostream& aOut, ErrorObserver& aErr); protected: @@ -160,7 +160,7 @@ protected: * @param aErr ErrorObserver * @result Document XML Document, or null on error */ - static Document* parsePath(const nsACString& aPath, ErrorObserver& aErr); + static txXPathNode* parsePath(const nsACString& aPath, ErrorObserver& aErr); }; #endif diff --git a/mozilla/extensions/transformiix/source/xslt/txStylesheet.cpp b/mozilla/extensions/transformiix/source/xslt/txStylesheet.cpp index 387f3d098d4..a723778704d 100644 --- a/mozilla/extensions/transformiix/source/xslt/txStylesheet.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txStylesheet.cpp @@ -136,14 +136,13 @@ txStylesheet::~txStylesheet() } txInstruction* -txStylesheet::findTemplate(Node* aNode, +txStylesheet::findTemplate(const txXPathNode& aNode, const txExpandedName& aMode, txIMatchContext* aContext, ImportFrame* aImportedBy, ImportFrame** aImportFrame) { NS_ASSERTION(aImportFrame, "missing ImportFrame pointer"); - NS_ASSERTION(aNode, "missing node"); *aImportFrame = nsnull; txInstruction* matchTemplate = nsnull; @@ -195,7 +194,7 @@ txStylesheet::findTemplate(Node* aNode, if (aMode.mLocalName) { aMode.mLocalName->ToString(mode); } - aNode->getNodeName(nodeName); + txXPathNodeUtils::getNodeName(aNode, nodeName); if (matchTemplate) { nsAutoString matchAttr; match->toString(matchAttr); @@ -214,16 +213,16 @@ txStylesheet::findTemplate(Node* aNode, #endif if (!matchTemplate) { - switch(aNode->getNodeType()) { - case Node::ELEMENT_NODE : - case Node::DOCUMENT_NODE : + switch (txXPathNodeUtils::getNodeType(aNode)) { + case txXPathNodeType::ELEMENT_NODE: + case txXPathNodeType::DOCUMENT_NODE: { matchTemplate = mContainerTemplate; break; } - case Node::ATTRIBUTE_NODE : - case Node::TEXT_NODE : - case Node::CDATA_SECTION_NODE : + case txXPathNodeType::ATTRIBUTE_NODE: + case txXPathNodeType::TEXT_NODE: + case txXPathNodeType::CDATA_SECTION_NODE: { matchTemplate = mCharactersTemplate; break; @@ -276,37 +275,37 @@ txStylesheet::getKeyMap() } PRBool -txStylesheet::isStripSpaceAllowed(Node* aNode, txIMatchContext* aContext) +txStylesheet::isStripSpaceAllowed(const txXPathNode& aNode, txIMatchContext* aContext) { PRInt32 frameCount = mStripSpaceTests.Count(); - if (!aNode || frameCount == 0) { + if (frameCount == 0) { return PR_FALSE; } - switch (aNode->getNodeType()) { - case Node::ELEMENT_NODE: - { - // check Whitespace stipping handling list against given Node - PRInt32 i; - for (i = 0; i < frameCount; ++i) { - txStripSpaceTest* sst = - NS_STATIC_CAST(txStripSpaceTest*, mStripSpaceTests[i]); - if (sst->matches(aNode, aContext)) { - if (sst->stripsSpace() && - !XMLUtils::getXMLSpacePreserve(aNode)) { - return MB_TRUE; - } - return MB_FALSE; - } - } - break; + txXPathTreeWalker walker(aNode); + + PRUint16 nodeType = walker.getNodeType(); + if (nodeType == txXPathNodeType::TEXT_NODE || + nodeType == txXPathNodeType::CDATA_SECTION_NODE) { + if (!txXPathNodeUtils::isWhitespace(aNode) || !walker.moveToParent()) { + return PR_FALSE; } - case Node::TEXT_NODE: - case Node::CDATA_SECTION_NODE: - { - if (!XMLUtils::isWhitespace(aNode)) - return MB_FALSE; - return isStripSpaceAllowed(aNode->getParentNode(), aContext); + nodeType = walker.getNodeType(); + } + + if (nodeType != txXPathNodeType::ELEMENT_NODE) { + return PR_FALSE; + } + + const txXPathNode& node = walker.getCurrentPosition(); + + // check Whitespace stipping handling list against given Node + PRInt32 i; + for (i = 0; i < frameCount; ++i) { + txStripSpaceTest* sst = + NS_STATIC_CAST(txStripSpaceTest*, mStripSpaceTests[i]); + if (sst->matches(node, aContext)) { + return sst->stripsSpace() && !XMLUtils::getXMLSpacePreserve(node); } } diff --git a/mozilla/extensions/transformiix/source/xslt/txStylesheet.h b/mozilla/extensions/transformiix/source/xslt/txStylesheet.h index 65fd2ab3773..bc6f76a403f 100644 --- a/mozilla/extensions/transformiix/source/xslt/txStylesheet.h +++ b/mozilla/extensions/transformiix/source/xslt/txStylesheet.h @@ -80,7 +80,7 @@ public: return mRefCnt; } - txInstruction* findTemplate(Node* aNode, + txInstruction* findTemplate(const txXPathNode& aNode, const txExpandedName& aMode, txIMatchContext* aContext, ImportFrame* aImportedBy, @@ -91,7 +91,8 @@ public: txOutputFormat* getOutputFormat(); GlobalVariable* getGlobalVariable(const txExpandedName& aName); const txExpandedNameMap& getKeyMap(); - PRBool isStripSpaceAllowed(Node* aNode, txIMatchContext* aContext); + PRBool isStripSpaceAllowed(const txXPathNode& aNode, + txIMatchContext* aContext); /** * Called by the stylesheet compiler once all stylesheets has been read. @@ -212,12 +213,12 @@ class txStripSpaceTest { public: txStripSpaceTest(nsIAtom* aPrefix, nsIAtom* aLocalName, PRInt32 aNSID, MBool stripSpace) - : mNameTest(aPrefix, aLocalName, aNSID, Node::ELEMENT_NODE), + : mNameTest(aPrefix, aLocalName, aNSID, txXPathNodeType::ELEMENT_NODE), mStrips(stripSpace) { } - MBool matches(Node* aNode, txIMatchContext* aContext) { + MBool matches(const txXPathNode& aNode, txIMatchContext* aContext) { return mNameTest.matches(aNode, aContext); } diff --git a/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.cpp b/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.cpp index 4bdb8b1b515..9e0405396c7 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.cpp @@ -44,6 +44,7 @@ #include "ExprResult.h" #include "txXSLTPatterns.h" #include "txIXPathContext.h" +#include "txXPathTreeWalker.h" nsresult txXSLTNumber::createNumber(Expr* aValueExpr, txPattern* aCountPattern, txPattern* aFromPattern, LevelType aLevel, @@ -139,54 +140,54 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern, txPattern* countPattern = aCountPattern; MBool ownsCountPattern = MB_FALSE; - Node* currNode = aContext->getContextNode(); + const txXPathNode& currNode = aContext->getContextNode(); // Parse count- and from-attributes if (!aCountPattern) { ownsCountPattern = MB_TRUE; txNodeTest* nodeTest = 0; - switch (currNode->getNodeType()) { - case Node::ELEMENT_NODE: + switch (txXPathNodeUtils::getNodeType(currNode)) { + case txXPathNodeType::ELEMENT_NODE: { - nsCOMPtr localName; - currNode->getLocalName(getter_AddRefs(localName)); - nodeTest = new txNameTest(0, localName, - currNode->getNamespaceID(), - Node::ELEMENT_NODE); + nsCOMPtr localName = + txXPathNodeUtils::getLocalName(currNode); + PRInt32 namespaceID = txXPathNodeUtils::getNamespaceID(currNode); + nodeTest = new txNameTest(0, localName, namespaceID, + txXPathNodeType::ELEMENT_NODE); break; } - case Node::TEXT_NODE: - case Node::CDATA_SECTION_NODE: + case txXPathNodeType::TEXT_NODE: + case txXPathNodeType::CDATA_SECTION_NODE: { nodeTest = new txNodeTypeTest(txNodeTypeTest::TEXT_TYPE); break; } - case Node::PROCESSING_INSTRUCTION_NODE: + case txXPathNodeType::PROCESSING_INSTRUCTION_NODE: { txNodeTypeTest* typeTest; typeTest = new txNodeTypeTest(txNodeTypeTest::PI_TYPE); if (typeTest) { nsAutoString nodeName; - currNode->getNodeName(nodeName); + txXPathNodeUtils::getNodeName(currNode, nodeName); typeTest->setNodeName(nodeName); } nodeTest = typeTest; break; } - case Node::COMMENT_NODE: + case txXPathNodeType::COMMENT_NODE: { nodeTest = new txNodeTypeTest(txNodeTypeTest::COMMENT_TYPE); break; } - case Node::DOCUMENT_NODE: - case Node::ATTRIBUTE_NODE: + case txXPathNodeType::DOCUMENT_NODE: + case txXPathNodeType::ATTRIBUTE_NODE: default: { // this won't match anything as we walk up the tree // but it's what the spec says to do nodeTest = new txNameTest(0, txXPathAtoms::_asterix, 0, - (Node::NodeType)currNode->getNodeType()); + txXPathNodeUtils::getNodeType(currNode)); break; } } @@ -205,36 +206,33 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern, // level = "single" if (aLevel == eLevelSingle) { - Node* node = currNode; - while (node) { - if (aFromPattern && node != currNode && - aFromPattern->matches(node, aContext)) { + txXPathTreeWalker walker(currNode); + do { + if (aFromPattern && !walker.isOnNode(currNode) && + aFromPattern->matches(walker.getCurrentPosition(), aContext)) { break; } - if (countPattern->matches(node, aContext)) { - aValues.add(NS_INT32_TO_PTR(getSiblingCount(node, countPattern, + if (countPattern->matches(walker.getCurrentPosition(), aContext)) { + aValues.add(NS_INT32_TO_PTR(getSiblingCount(walker, countPattern, aContext))); break; } - node = node->getXPathParent(); - } + } while (walker.moveToParent()); // Spec says to only match ancestors that are decendants of the // ancestor that matches the from-pattern, so keep going to make // sure that there is an ancestor that does. if (aFromPattern && aValues.getLength()) { - node = node->getXPathParent(); - while (node) { - if (aFromPattern->matches(node, aContext)) { + PRBool hasParent; + while ((hasParent = walker.moveToParent())) { + if (aFromPattern->matches(walker.getCurrentPosition(), aContext)) { break; } - - node = node->getXPathParent(); } - if (!node) { + if (!hasParent) { aValues.clear(); } } @@ -242,23 +240,21 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern, // level = "multiple" else if (aLevel == eLevelMultiple) { // find all ancestor-or-selfs that matches count until... - Node* node = currNode; + txXPathTreeWalker walker(currNode); MBool matchedFrom = MB_FALSE; - while (node) { - if (aFromPattern && node != currNode && - aFromPattern->matches(node, aContext)) { + do { + if (aFromPattern && !walker.isOnNode(currNode) && + aFromPattern->matches(walker.getCurrentPosition(), aContext)) { //... we find one that matches from matchedFrom = MB_TRUE; break; } - if (countPattern->matches(node, aContext)) { - aValues.add(NS_INT32_TO_PTR(getSiblingCount(node, countPattern, + if (countPattern->matches(walker.getCurrentPosition(), aContext)) { + aValues.add(NS_INT32_TO_PTR(getSiblingCount(walker, countPattern, aContext))); } - - node = node->getXPathParent(); - } + } while (walker.moveToParent()); // Spec says to only match ancestors that are decendants of the // ancestor that matches the from-pattern, so if none did then @@ -269,23 +265,22 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern, } // level = "any" else if (aLevel == eLevelAny) { - Node* node = currNode; PRInt32 value = 0; MBool matchedFrom = MB_FALSE; - while (node) { - if (aFromPattern && node != currNode && - aFromPattern->matches(node, aContext)) { + txXPathTreeWalker walker(currNode); + do { + if (aFromPattern && !walker.isOnNode(currNode) && + aFromPattern->matches(walker.getCurrentPosition(), aContext)) { matchedFrom = MB_TRUE; break; } - if (countPattern->matches(node, aContext)) { + if (countPattern->matches(walker.getCurrentPosition(), aContext)) { ++value; } - node = getPrevInDocumentOrder(node); - } + } while (getPrevInDocumentOrder(walker)); // Spec says to only count nodes that follows the first node that // matches the from pattern. So so if none did then we shouldn't @@ -439,34 +434,29 @@ txXSLTNumber::getCounters(Expr* aGroupSize, Expr* aGroupSeparator, } PRInt32 -txXSLTNumber::getSiblingCount(Node* aNode, txPattern* aCountPattern, +txXSLTNumber::getSiblingCount(txXPathTreeWalker& aWalker, + txPattern* aCountPattern, txIMatchContext* aContext) { PRInt32 value = 1; - Node* node = aNode->getPreviousSibling(); - - while (node) { - if (aCountPattern->matches(node, aContext)) { + while (aWalker.moveToPreviousSibling()) { + if (aCountPattern->matches(aWalker.getCurrentPosition(), aContext)) { ++value; } - node = node->getPreviousSibling(); } return value; } -Node* -txXSLTNumber::getPrevInDocumentOrder(Node* aNode) +PRBool +txXSLTNumber::getPrevInDocumentOrder(txXPathTreeWalker& aWalker) { - Node* prev = aNode->getPreviousSibling(); - if (prev) { - Node* lastChild = prev->getLastChild(); - while (lastChild) { - prev = lastChild; - lastChild = prev->getLastChild(); + if (aWalker.moveToPreviousSibling()) { + while (aWalker.moveToLastChild()) { + // do nothing } - return prev; + return PR_TRUE; } - return aNode->getXPathParent(); + return aWalker.moveToParent(); } #define TX_CHAR_RANGE(ch, a, b) if (ch < a) return MB_FALSE; \ diff --git a/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.h b/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.h index c6e9ae6aa53..4a4c59e9db3 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.h +++ b/mozilla/extensions/transformiix/source/xslt/txXSLTNumber.h @@ -44,10 +44,10 @@ #include "nsString.h" class Expr; -class Node; class txPattern; class txIEvalContext; class txIMatchContext; +class txXPathTreeWalker; class txXSLTNumber { public: @@ -74,11 +74,17 @@ private: txList& aCounters, nsAString& aHead, nsAString& aTail); - static PRInt32 getSiblingCount(Node* aNode, txPattern* aCountPattern, + /** + * getSiblingCount uses aWalker to walk the siblings of aWalker's current + * position. + * + */ + static PRInt32 getSiblingCount(txXPathTreeWalker& aWalker, + txPattern* aCountPattern, txIMatchContext* aContext); - static Node* getPrevInDocumentOrder(Node* aNode); - + static PRBool getPrevInDocumentOrder(txXPathTreeWalker& aWalker); + static MBool isAlphaNumeric(PRUnichar ch); }; diff --git a/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.cpp b/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.cpp index 3d2fe186b7f..24577f1d5b1 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.cpp @@ -108,7 +108,7 @@ double txUnionPattern::getDefaultPriority() * This should be called on the simple patterns for xsl:template, * but is fine for xsl:key and xsl:number */ -MBool txUnionPattern::matches(Node* aNode, txIMatchContext* aContext) +MBool txUnionPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) { txListIterator iter(&mLocPathPatterns); while (iter.hasNext()) { @@ -182,9 +182,9 @@ nsresult txLocPathPattern::addStep(txPattern* aPattern, MBool isChild) return NS_OK; } -MBool txLocPathPattern::matches(Node* aNode, txIMatchContext* aContext) +MBool txLocPathPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) { - NS_ASSERTION(aNode && mSteps.getLength(), "Internal error"); + NS_ASSERTION(mSteps.getLength(), "Internal error"); /* * The idea is to split up a path into blocks separated by descendant @@ -205,40 +205,42 @@ MBool txLocPathPattern::matches(Node* aNode, txIMatchContext* aContext) step = (Step*)iter.previous(); if (!step->pattern->matches(aNode, aContext)) return MB_FALSE; - Node* node = aNode->getXPathParent(); + + txXPathTreeWalker walker(aNode); + PRBool hasParent = walker.moveToParent(); while (step->isChild) { step = (Step*)iter.previous(); if (!step) return MB_TRUE; // all steps matched - if (!node || !step->pattern->matches(node, aContext)) + if (!hasParent || !step->pattern->matches(walker.getCurrentPosition(), aContext)) return MB_FALSE; // no more ancestors or no match - node = node->getXPathParent(); + hasParent = walker.moveToParent(); } // We have at least one // path separator - Node *blockStart = node; + txXPathTreeWalker blockWalker(walker); txListIterator blockIter(iter); while ((step = (Step*)iter.previous())) { - if (!node) + if (!hasParent) return MB_FALSE; // There are more steps in the current block // than ancestors of the tested node - if (!step->pattern->matches(node, aContext)) { + if (!step->pattern->matches(walker.getCurrentPosition(), aContext)) { // Didn't match. We restart at beginning of block using a new // start node iter = blockIter; - blockStart = blockStart->getXPathParent(); - node = blockStart; + hasParent = blockWalker.moveToParent(); + walker.moveTo(blockWalker); } else { - node = node->getXPathParent(); + hasParent = walker.moveToParent(); if (!step->isChild) { // We've matched an entire block. Set new start iter and start node blockIter = iter; - blockStart = node; + blockWalker.moveTo(walker); } } } @@ -288,9 +290,9 @@ txRootPattern::~txRootPattern() { } -MBool txRootPattern::matches(Node* aNode, txIMatchContext* aContext) +MBool txRootPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) { - return aNode && (aNode->getNodeType() == Node::DOCUMENT_NODE); + return (txXPathNodeUtils::getNodeType(aNode) == txXPathNodeType::DOCUMENT_NODE); } double txRootPattern::getDefaultPriority() @@ -339,19 +341,23 @@ txIdPattern::~txIdPattern() { } -MBool txIdPattern::matches(Node* aNode, txIMatchContext* aContext) +MBool txIdPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) { - if (aNode->getNodeType() != Node::ELEMENT_NODE) { + if (txXPathNodeUtils::getNodeType(aNode) != txXPathNodeType::ELEMENT_NODE) { return MB_FALSE; } // Get a ID attribute, if there is nsAutoString value; #ifdef TX_EXE - if (!((Element*)aNode)->getIDValue(value)) - return MB_FALSE; + Element* elem; + nsresult rv = txXPathNativeNode::getElement(aNode, &elem); + NS_ASSERTION(NS_SUCCEEDED(rv), "So why claim it's an element above?"); + if (!elem->getIDValue(value)) { + return PR_FALSE; + } #else - nsCOMPtr content = do_QueryInterface(aNode->getNSObj()); + nsIContent* content = txXPathNativeNode::getContent(aNode); NS_ASSERTION(content, "a Element without nsIContent"); if (!content) { return MB_FALSE; @@ -405,16 +411,14 @@ txKeyPattern::~txKeyPattern() { } -MBool txKeyPattern::matches(Node* aNode, txIMatchContext* aContext) +MBool txKeyPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) { txExecutionState* es = (txExecutionState*)aContext->getPrivateContext(); - Document* contextDoc; - if (aNode->getNodeType() == Node::DOCUMENT_NODE) - contextDoc = (Document*)aNode; - else - contextDoc = aNode->getOwnerDocument(); + nsAutoPtr contextDoc(txXPathNodeUtils::getOwnerDocument(aNode)); + NS_ENSURE_TRUE(contextDoc, PR_FALSE); + nsRefPtr nodes; - nsresult rv = es->getKeyNodes(mName, contextDoc, mValue, PR_TRUE, + nsresult rv = es->getKeyNodes(mName, *contextDoc, mValue, PR_TRUE, getter_AddRefs(nodes)); NS_ENSURE_SUCCESS(rv, PR_FALSE); @@ -459,17 +463,18 @@ txStepPattern::~txStepPattern() delete mNodeTest; } -MBool txStepPattern::matches(Node* aNode, txIMatchContext* aContext) +MBool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext) { - NS_ASSERTION(mNodeTest && aNode, "Internal error"); - if (!aNode) - return MB_FALSE; + NS_ASSERTION(mNodeTest, "Internal error"); if (!mNodeTest->matches(aNode, aContext)) return MB_FALSE; - if (!mIsAttr && !aNode->getParentNode()) + txXPathTreeWalker walker(aNode); + if ((!mIsAttr && walker.getNodeType() == txXPathNodeType::ATTRIBUTE_NODE) || + !walker.moveToParent()) { return MB_FALSE; + } if (isEmpty()) { return MB_TRUE; } @@ -497,25 +502,14 @@ MBool txStepPattern::matches(Node* aNode, txIMatchContext* aContext) nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes)); NS_ENSURE_SUCCESS(rv, rv); - Node* parent = aNode->getXPathParent(); - if (mIsAttr) { - NamedNodeMap* atts = parent->getAttributes(); - if (atts) { - PRUint32 i; - for (i = 0; i < atts->getLength(); i++) { - Node* attr = atts->item(i); - if (mNodeTest->matches(attr, aContext)) - nodes->append(attr); - } - } - } - else { - Node* tmpNode = parent->getFirstChild(); - while (tmpNode) { - if (mNodeTest->matches(tmpNode, aContext)) - nodes->append(tmpNode); - tmpNode = tmpNode->getNextSibling(); + PRBool hasNext = mIsAttr ? walker.moveToFirstAttribute() : + walker.moveToFirstChild(); + while (hasNext) { + if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) { + nodes->append(walker.getCurrentPosition()); } + hasNext = mIsAttr ? walker.moveToNextAttribute() : + walker.moveToNextSibling(); } txListIterator iter(&predicates); @@ -539,7 +533,7 @@ MBool txStepPattern::matches(Node* aNode, txIMatchContext* aContext) // handle default, [position() == numberValue()] if ((double)predContext.position() == exprResult->numberValue()) { - Node* tmp = predContext.getContextNode(); + const txXPathNode& tmp = predContext.getContextNode(); if (tmp == aNode) contextIsInPredicate = MB_TRUE; newNodes->append(tmp); @@ -547,7 +541,7 @@ MBool txStepPattern::matches(Node* aNode, txIMatchContext* aContext) break; default: if (exprResult->booleanValue()) { - Node* tmp = predContext.getContextNode(); + const txXPathNode& tmp = predContext.getContextNode(); if (tmp == aNode) contextIsInPredicate = MB_TRUE; newNodes->append(tmp); @@ -557,7 +551,7 @@ MBool txStepPattern::matches(Node* aNode, txIMatchContext* aContext) } // Move new NodeSet to the current one nodes->clear(); - nodes->append(newNodes); + nodes->append(*newNodes); if (!contextIsInPredicate) { return MB_FALSE; } diff --git a/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.h b/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.h index 3b06d7b37dc..58377b3dfe0 100644 --- a/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.h +++ b/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.h @@ -53,7 +53,8 @@ public: /* * Determines whether this Pattern matches the given node. */ - virtual MBool matches(Node* aNode, txIMatchContext* aContext) = 0; + virtual MBool matches(const txXPathNode& aNode, + txIMatchContext* aContext) = 0; /* * Returns the default priority of this Pattern. @@ -85,7 +86,7 @@ public: }; #define TX_DECL_PATTERN \ - MBool matches(Node* aNode, txIMatchContext* aContext); \ + MBool matches(const txXPathNode& aNode, txIMatchContext* aContext); \ double getDefaultPriority(); \ void toString(nsAString& aDest) #define TX_DECL_PATTERN2 \ diff --git a/mozilla/extensions/transformiix/source/xslt/util/Makefile.in b/mozilla/extensions/transformiix/source/xslt/util/Makefile.in index 6fdf65c8cc3..661c79b7031 100644 --- a/mozilla/extensions/transformiix/source/xslt/util/Makefile.in +++ b/mozilla/extensions/transformiix/source/xslt/util/Makefile.in @@ -36,6 +36,7 @@ REQUIRES += dom \ widget \ locale \ unicharutil \ + necko \ $(NULL) endif diff --git a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp index 580bc4c80a1..37de6a1a8cf 100644 --- a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp +++ b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp @@ -45,7 +45,6 @@ #include "ExprResult.h" #include "Expr.h" #include "txStringUtils.h" -#include "txNodeSet.h" #include "prmem.h" #include "nsQuickSort.h" diff --git a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.h b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.h index 452a3393a37..53ca7e5faba 100644 --- a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.h +++ b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.h @@ -43,10 +43,10 @@ #include "baseutils.h" #include "List.h" #include "nsIAtom.h" +#include "txXPathNode.h" class Element; class Expr; -class Node; class txExecutionState; class txNodeSet; class TxObject;