diff --git a/mozilla/extensions/transformiix/source/xpath/AttributeExpr.cpp b/mozilla/extensions/transformiix/source/xpath/AttributeExpr.cpp index b7ce6bcb767..b9b26725945 100644 --- a/mozilla/extensions/transformiix/source/xpath/AttributeExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/AttributeExpr.cpp @@ -69,27 +69,8 @@ AttributeExpr::AttributeExpr(String& name) * @return the result of the evaluation **/ ExprResult* AttributeExpr::evaluate(Node* context, ContextState* cs) { - - NodeSet* nodeSet = new NodeSet(); - if ( !context ) return nodeSet; - NamedNodeMap* atts = context->getAttributes(); - if ( atts ) { - PRUint32 i = 0; - if ( isNameWild && isNamespaceWild ) { - for ( ; i < atts->getLength(); i++ ) - nodeSet->add(atts->item(i)); - } - else { - for ( ; i < atts->getLength(); i++ ) { - Node* attr = atts->item(i); - if (matches(attr, context, cs)) { - nodeSet->add(attr); - if (!isNameWild) break; - } - } - } - } - return nodeSet; + NS_ASSERTION(0, "AttributeExpr::evaluate called"); + return 0; } //-- evaluate /** diff --git a/mozilla/extensions/transformiix/source/xpath/BasicNodeExpr.cpp b/mozilla/extensions/transformiix/source/xpath/BasicNodeExpr.cpp index 1702977b5df..6dabc4a5d3d 100644 --- a/mozilla/extensions/transformiix/source/xpath/BasicNodeExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/BasicNodeExpr.cpp @@ -56,16 +56,8 @@ void BasicNodeExpr::setNodeName(const String& name) { * @return the result of the evaluation **/ ExprResult* BasicNodeExpr::evaluate(Node* context, ContextState* cs) { - NodeSet* nodeSet = new NodeSet(); - if (!context) - return nodeSet; - Node* node = context->getFirstChild(); - while (node) { - if (matches(node, context, cs)) - nodeSet->add(node); - node = node->getNextSibling(); - } - return nodeSet; + NS_ASSERTION(0, "BasicNodeExpr::evaluate called"); + return 0; } //-- evaluate /** diff --git a/mozilla/extensions/transformiix/source/xpath/ElementExpr.cpp b/mozilla/extensions/transformiix/source/xpath/ElementExpr.cpp index c2f3d64c7cc..c09a6fb9af7 100644 --- a/mozilla/extensions/transformiix/source/xpath/ElementExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/ElementExpr.cpp @@ -63,18 +63,8 @@ ElementExpr::ElementExpr(String& name) * @return the result of the evaluation **/ ExprResult* ElementExpr::evaluate(Node* context, ContextState* cs) { - - NodeSet* nodeSet = new NodeSet(); - - if ( !context ) return nodeSet; - - Node* node = context->getFirstChild(); - while (node) { - if (matches(node, context, cs)) - nodeSet->add(node); - node = node->getNextSibling(); - } - return nodeSet; + NS_ASSERTION(0, "ElementExpr::evaluate called"); + return 0; } //-- evaluate /** diff --git a/mozilla/extensions/transformiix/source/xpath/Expr.h b/mozilla/extensions/transformiix/source/xpath/Expr.h index 9dcb61a1b35..f46a3e0d06e 100644 --- a/mozilla/extensions/transformiix/source/xpath/Expr.h +++ b/mozilla/extensions/transformiix/source/xpath/Expr.h @@ -87,14 +87,6 @@ public: **/ virtual FunctionCall* resolveFunctionCall(const String& name) = 0; - /** - * Sorts the given NodeSet by DocumentOrder. - * @param nodes the NodeSet to sort - * - * Note: I will be moving this functionality elsewhere soon - **/ - virtual void sortByDocumentOrder(NodeSet* nodes) = 0; - /** * Returns the namespace URI for the given namespace prefix, this method should * only be called for determining a namespace declared within the context diff --git a/mozilla/extensions/transformiix/source/xpath/FilterExpr.cpp b/mozilla/extensions/transformiix/source/xpath/FilterExpr.cpp index 70946f59f36..0be6684cd21 100644 --- a/mozilla/extensions/transformiix/source/xpath/FilterExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/FilterExpr.cpp @@ -67,7 +67,6 @@ ExprResult* FilterExpr::evaluate(Node* context, ContextState* cs) { if (exprResult->getResultType() == ExprResult::NODESET) { // Result is a nodeset, filter it. - cs->sortByDocumentOrder((NodeSet*)exprResult); evaluatePredicates((NodeSet*)exprResult, cs); } else if(!isEmpty()) { diff --git a/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp index c2b6bbafdff..5decbc12b88 100644 --- a/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp @@ -182,10 +182,7 @@ NodeSet* FunctionCall::evaluateToNodeSet(Expr* aExpr, return 0; } - NodeSet* nodes = (NodeSet*)exprResult; - aCs->sortByDocumentOrder(nodes); - - return nodes; + return (NodeSet*)exprResult; } /** diff --git a/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp b/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp index 658ec7dd2df..0e5511b1d95 100644 --- a/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp +++ b/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp @@ -62,8 +62,11 @@ LocationStep::~LocationStep() { **/ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) { - NodeSet* nodes = new NodeSet(); - if (( !context ) || (! nodeExpr )) return nodes; + NodeSet* nodes = new NodeSet(); + if (!context || !nodeExpr || !nodes) + return nodes; + + MBool reverse = MB_FALSE; Node* node = context; switch (axisIdentifier) { @@ -71,9 +74,10 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) { node = context->getXPathParent(); //-- do not break here case ANCESTOR_OR_SELF_AXIS : + reverse = MB_TRUE; while (node) { if (nodeExpr->matches(node, context, cs)) { - nodes->add(node); + nodes->append(node); } node = node->getXPathParent(); } @@ -81,17 +85,18 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) { case ATTRIBUTE_AXIS : { NamedNodeMap* atts = context->getAttributes(); - if ( atts ) { - for ( PRUint32 i = 0; i < atts->getLength(); i++ ) { + if (atts) { + for (PRUint32 i = 0; i < atts->getLength(); i++) { Node* attr = atts->item(i); - if ( nodeExpr->matches(attr, context, cs) ) nodes->add(attr); + if (nodeExpr->matches(attr, context, cs)) + nodes->append(attr); } } break; } case DESCENDANT_OR_SELF_AXIS : - if ( nodeExpr->matches(context, context, cs)) - nodes->add(context); + if (nodeExpr->matches(context, context, cs)) + nodes->append(context); //-- do not break here case DESCENDANT_AXIS : fromDescendants(context, cs, nodes); @@ -109,7 +114,7 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) { node = node->getNextSibling(); if (nodeExpr->matches(node, context, cs)) - nodes->add(node); + nodes->append(node); if (node->hasChildNodes()) fromDescendants(node, cs, nodes); @@ -124,7 +129,7 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) { node = context->getNextSibling(); while (node) { if (nodeExpr->matches(node, context, cs)) - nodes->add(node); + nodes->append(node); node = node->getNextSibling(); } break; @@ -138,10 +143,11 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) { { Node* parent = context->getXPathParent(); if ( nodeExpr->matches(parent, context, cs) ) - nodes->add(parent); + nodes->append(parent); break; } case PRECEDING_AXIS : + reverse = MB_TRUE; while (node && !node->getPreviousSibling()) { node = node->getXPathParent(); } @@ -152,7 +158,7 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) { fromDescendantsRev(node, cs, nodes); if (nodeExpr->matches(node, context, cs)) - nodes->add(node); + nodes->append(node); while (node && !node->getPreviousSibling()) { node = node->getParentNode(); @@ -160,23 +166,24 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) { } break; case PRECEDING_SIBLING_AXIS: + reverse = MB_TRUE; node = context->getPreviousSibling(); while (node) { if (nodeExpr->matches(node, context, cs)) - nodes->add(node); + nodes->append(node); node = node->getPreviousSibling(); } break; case SELF_AXIS : - if ( nodeExpr->matches(context, context, cs) ) - nodes->add(context); + if (nodeExpr->matches(context, context, cs)) + nodes->append(context); break; default: //-- Children Axis { Node* tmpNode = context->getFirstChild(); while (tmpNode) { - if ( nodeExpr->matches(tmpNode, context, cs) ) - nodes->add(tmpNode); + if (nodeExpr->matches(tmpNode, context, cs)) + nodes->append(tmpNode); tmpNode = tmpNode->getNextSibling(); } break; @@ -186,6 +193,9 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) { //-- apply predicates evaluatePredicates(nodes, cs); + if (reverse) + nodes->reverse(); + return nodes; } //-- evaluate @@ -207,7 +217,7 @@ void LocationStep::fromDescendants(Node* context, ContextState* cs, NodeSet* nod Node* child = context->getFirstChild(); while (child) { if (nodeExpr->matches(child, context, cs)) - nodes->add(child); + nodes->append(child); //-- check childs descendants if (child->hasChildNodes()) fromDescendants(child, cs, nodes); @@ -228,7 +238,7 @@ void LocationStep::fromDescendantsRev(Node* context, ContextState* cs, NodeSet* fromDescendantsRev(child, cs, nodes); if (nodeExpr->matches(child, context, cs)) - nodes->add(child); + nodes->append(child); child = child->getPreviousSibling(); } diff --git a/mozilla/extensions/transformiix/source/xpath/NodeSet.cpp b/mozilla/extensions/transformiix/source/xpath/NodeSet.cpp index b298e123157..efe350c5568 100644 --- a/mozilla/extensions/transformiix/source/xpath/NodeSet.cpp +++ b/mozilla/extensions/transformiix/source/xpath/NodeSet.cpp @@ -32,325 +32,439 @@ #include "NodeSet.h" #include "XMLDOMUtils.h" -#ifdef TX_EXE -#include -#endif +#include "string.h" +#include "stdio.h" -/** - * NodeSet - * This class was ported from XSL:P. -**/ +static const int kTxNodeSetMinSize = 4; +static const int kTxNodeSetGrowFactor = 2; +/* + * Implementation of an XPath NodeSet + */ - //-------------/ - //- Constants -/ -//-------------/ -const int NodeSet::DEFAULT_SIZE = 25; - - - //----------------/ - //- Constructors -/ -//----------------/ - -/** - * Creates a new NodeSet with the default Size -**/ -NodeSet::NodeSet() { - initialize(DEFAULT_SIZE); -} //-- NodeSet - -/** - * Creates a new NodeSet with the default Size -**/ -NodeSet::NodeSet(int size) { - initialize(size); -} //-- NodeSet - -/** - * Creates a new NodeSet, copying the Node references from the source - * NodeSet -**/ -NodeSet::NodeSet(const NodeSet& source) { - initialize(source.size()); - source.copyInto(*this); -} //--NodeSet - -/** - * Helper method for Constructors -**/ -void NodeSet::initialize(int size) { - checkDuplicates = MB_TRUE; - elements = new Node*[size]; - for ( int i = 0; i < size; i++ ) elements[i] = 0; - elementCount = 0; - bufferSize = size; - initialSize = size; -} //-- initialize - -/** - * Destructor for NodeSet -**/ -NodeSet::~NodeSet() { - delete [] elements; -} //-- ~NodeSet - -/** - * Adds the specified Node to this NodeSet if it is not already - * contained within in this NodeSet. - * @param node the Node to add to the NodeSet - * @return true if the Node is added to the NodeSet -**/ -MBool NodeSet::add(Node* node) { - - if (node) { - if (checkDuplicates && contains(node)) return MB_FALSE; - if (elementCount == bufferSize) increaseSize(); - elements[elementCount++] = node; - return MB_TRUE; - } - return MB_FALSE; -} //-- add - -/** - * Adds the specified Node to the NodeSet at the specified index, - * as long as the Node is not already contained within the set - * @param node the Node to add to the NodeSet - * @return true if the Node is added to the NodeSet. If the index is - * out of bounds the Node will not be added to the set and false will be returned. -**/ -MBool NodeSet::add(int index, Node* node) +/* + * Creates a new empty NodeSet + */ +NodeSet::NodeSet() : mElements(0), + mBufferSize(0), + mElementCount(0) { - if (!node || (index < 0) || (index > elementCount)) return MB_FALSE; +} - if (checkDuplicates && contains(node)) return MB_FALSE; - - // make sure we have room to add the object - if (elementCount == bufferSize) increaseSize(); - - if (index == elementCount) { - elements[elementCount++] = node; +/* + * Creates a new NodeSet containing the supplied Node + */ +NodeSet::NodeSet(Node* aNode) : mBufferSize(1), + mElementCount(1) +{ + NS_ASSERTION(aNode, "missing node to NodeSet::add") + mElements = new Node*[1]; + if (!mElements) { + NS_ASSERTION(0, "out of memory"); + mBufferSize = 0; + mElementCount = 0; } else { - shiftUp(index); - elements[index] = node; - ++elementCount; + mElements[0] = aNode; } - return MB_TRUE; -} //-- add +} -/** - * Removes all elements from the list -**/ -void NodeSet::clear() { - for (int i = 0; i < elementCount; i++) { - elements[i] = 0; +/* + * Creates a new NodeSet, copying the Node references from the source + * NodeSet + */ +NodeSet::NodeSet(const NodeSet& aSource) : mElements(0), + mBufferSize(0), + mElementCount(0) +{ + 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 NodeSet::add(Node* aNode) +{ + NS_ASSERTION(aNode, "missing node to NodeSet::add") + if (!aNode) + return NS_ERROR_NULL_POINTER; + + 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; } - elementCount = 0; -} //-- clear + return NS_OK; +} -/** - * Returns true if the specified Node is contained in the set. - * if the specfied Node is null, then if the NodeSet contains a null - * value, true will be returned. - * @param node the element to search the NodeSet for - * @return true if specified Node is contained in the NodeSet -**/ -MBool NodeSet::contains(Node* node) { - return (MBool)(indexOf(node) >= 0); -} //-- contains +/* + * 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. + */ -/** - * Copies the elements of this NodeSet, into the destination NodeSet -**/ -void NodeSet::copyInto(NodeSet& dest) const { - for ( int i = 0; i < elementCount; i++ ) dest.add(elements[i]); -} //-- copyInto +/* + * 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") + * + * 1 3 7 <- source 1 + * 2 3 6 8 9 <- source 2 + * _ _ _ _ _ _ _ _ <- 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: + * + * 1 3 <- source 1 + * 2 3 6 <- source 2 + * _ _ _ _ _ 7 8 9 <- 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. + */ +nsresult NodeSet::add(const NodeSet* aNodes) +{ + NS_ASSERTION(aNodes, "missing nodeset to NodeSet::add") + if (!aNodes) + return NS_ERROR_NULL_POINTER; -/** - * Returns the Node at the specified position in this NodeSet. - * @param index the position of the Node to return -**/ -Node* NodeSet::get(int index) { - if ((index < 0) || index >= elementCount) return 0; - return elements[index]; -} //-- get + if (aNodes->mElementCount == 0) + return NS_OK; -/** - * Returns true if duplicate checking is enabled, otherwise false. - * - * @return true if duplicate checking is enabled, otherwise false. -**/ -MBool NodeSet::getDuplicateChecking() { - return checkDuplicates; -} //-- getDuplicateChecking + // 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)) + 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); + + // Move nodes in this nodeset + lastInsertPos -= thisPos - pos + 1; + memmove(mElements + lastInsertPos, + mElements + pos, + (thisPos - pos + 1) * sizeof(Node*)); + + // 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; + } + 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); + + // Copy nodes from other nodeset to this + lastInsertPos -= otherPos - pos + 1; + memcpy(mElements + lastInsertPos, + aNodes->mElements + pos, + (otherPos - pos + 1) * sizeof(Node*)); + + // 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; + } + } + + 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. + * 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. + */ + +/* + * 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 NodeSet::append(Node* aNode) +{ + NS_ASSERTION(aNode, "missing node to NodeSet::append") + if (!aNode) + return NS_ERROR_NULL_POINTER; + + if (!ensureSize(mElementCount + 1)) + return NS_ERROR_OUT_OF_MEMORY; + + mElements[mElementCount++] = 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 NodeSet::append(const NodeSet* aNodes) +{ + NS_ASSERTION(aNodes, "missing nodeset to NodeSet::append") + if (!aNodes) + return NS_ERROR_NULL_POINTER; + + if (!ensureSize(mElementCount + aNodes->mElementCount)) + return NS_ERROR_OUT_OF_MEMORY; + + memcpy(mElements + mElementCount, + aNodes->mElements, + aNodes->mElementCount * sizeof(Node*)); + mElementCount += aNodes->mElementCount; + + return NS_OK; +} + +/* + * Reverse the order of the nodes. + */ +void NodeSet::reverse() +{ + 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; + } +} + +/* * Returns the index of the specified Node, * or -1 if the Node is not contained in the NodeSet - * @param node the Node to get the index for -**/ -int NodeSet::indexOf(Node* node) { - for (int i = 0; i < elementCount; i++) - if (node == elements[i]) return i; - return -1; -} //-- indexOf + * @param aNode the Node to get the index for + * @return index of specified node or -1 if the node does not exist + */ +MBool NodeSet::indexOf(Node* aNode) const +{ + // XXX evaluate cost of this + // Workaround to fix the fact that attributes can't be + // pointer-compared + MBool nonDup; + int pos = findPosition(aNode, 0, mElementCount - 1, nonDup); + return nonDup ? -1 : pos; +} -/** - * Returns true if there are no Nodes in the NodeSet. - * @return true if there are no Nodes in the NodeSet. -**/ -MBool NodeSet::isEmpty() { - return (elementCount == 0) ? MB_TRUE : MB_FALSE; -} //-- isEmpty +/* + * 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* NodeSet::get(int aIndex) const +{ + NS_ASSERTION(aIndex >= 0 && aIndex < mElementCount, + "invalid index in NodeSet::get") + if (aIndex < 0 || aIndex >= mElementCount) + return 0; -/** - * Removes the Node at the specified index from the NodeSet - * @param index the position in the NodeSet to remove the Node from - * @return the Node that was removed from the list -**/ -Node* NodeSet::remove(int index) { + return mElements[aIndex]; +} - if ((index < 0) || (index >= elementCount)) return 0; - - Node* node = elements[index]; - shiftDown(index+1); - --elementCount; - return node; -} //-- remove - -/** - * Removes the the specified Node from the NodeSet - * @param node the Node to remove from the NodeSet - * @return true if the Node was removed from the list -**/ -MBool NodeSet::remove(Node* node) { - int index = indexOf(node); - - if (index > -1) { - remove(index); - } - else return MB_FALSE; - - return MB_TRUE; -} //-- remove - -/** - * Enables or disables checking for duplicates. By default - * the #add method will check for duplicate nodes. This should - * only be disabled when no possibility of duplicates could occur. - * - * @param checkDuplicates an MBool indicating, when true, to perform duplicate checking, - * otherwise duplicate checking is disabled. -**/ -void NodeSet::setDuplicateChecking(MBool checkDuplicates) { - this->checkDuplicates = checkDuplicates; -} //-- setDuplicateChecking - -/** - * Returns the number of elements in the NodeSet - * @return the number of elements in the NodeSet -**/ -int NodeSet::size() const{ - return elementCount; -} //-- size - -/** - * Creates a String representation of this NodeSet - * @param str the destination string to append the String representation to. -**/ -void NodeSet::toString(String& str) { - str.append("#NodeSet"); -} //-- toString - - //-------------------/ - //- Private Methods -/ -//-------------------/ - -/** - * increase the NodeSet capacity by a factor of its initial size -**/ -void NodeSet::increaseSize() { - - bufferSize += bufferSize; - Node** tmpNodes = elements; - elements = new Node*[bufferSize]; - int i=0; - for (i=0;i < elementCount; i++) elements[i] = tmpNodes[i]; - for (;i elementCount)) return; - - //-- from Java - //-- System.arraycopy(elements, index, elements, index - 1, elementCount - index); - for (int i = index; i < elementCount; i++) { - elements[i-1] = elements[i]; - } - - elements[elementCount-1] = 0; -} //-- shiftDown - -/** - * Shifts all elements at the specified index up by 1 -**/ -void NodeSet::shiftUp(int index) { - if (index == elementCount) return; - if (elementCount == bufferSize) increaseSize(); - - //-- from Java - //-- System.arraycopy(elements, index, elements, index + 1, elementCount - index); - for (int i = elementCount; i > index; i--) { - elements[i] = elements[i-1]; - } -} //-- shiftUp - - //------------------------------------/ - //- Virtual Methods from: ExprResult -/ -//------------------------------------/ - -/** +/* * Returns the type of ExprResult represented * @return the type of ExprResult represented -**/ -short NodeSet::getResultType() { + */ +short NodeSet::getResultType() +{ return ExprResult::NODESET; -} //-- getResultType +} -/** +/* * Converts this ExprResult to a Boolean (MBool) value * @return the Boolean value -**/ -MBool NodeSet::booleanValue() { - return (MBool) (size() > 0); -} //- booleanValue + */ +MBool NodeSet::booleanValue() +{ + return mElementCount > 0; +} -/** +/* * Converts this ExprResult to a Number (double) value * @return the Number value -**/ -double NodeSet::numberValue() { - // OG+ - // As per the XPath spec, the number value of a node-set is the number value - // of its string value. - String str; - stringValue(str); - return Double::toDouble(str); - // OG- -} //-- numberValue + */ +double NodeSet::numberValue() +{ + String str; + stringValue(str); + return Double::toDouble(str); +} -/** +/* * Creates a String representation of this ExprResult - * @param str the destination string to append the String representation to. -**/ -void NodeSet::stringValue(String& str) { - if ( size()>0) { - // XXX Sort by document order here - XMLDOMUtils::getNodeValue(get(0), str); + * @param aStr the destination string to append the String representation to. + */ +void NodeSet::stringValue(String& aStr) +{ + if (mElementCount > 0) + XMLDOMUtils::getNodeValue(get(0), aStr); +} + +/* + * 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 NodeSet::ensureSize(int aSize) +{ + if (aSize <= mBufferSize) + return MB_TRUE; + + // This isn't 100% safe. But until someone manages to make a 1gig nodeset + // it should be ok. + int newSize = mBufferSize ? mBufferSize : kTxNodeSetMinSize; + while (newSize < aSize) + newSize *= kTxNodeSetGrowFactor; + + Node** newArr = new Node*[newSize]; + if (!newArr) + return MB_FALSE; + + if (mElementCount) + memcpy(newArr, mElements, mElementCount * sizeof(Node*)); + + delete [] mElements; + mElements = newArr; + mBufferSize = newSize; + + return MB_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 NodeSet::findPosition(Node* aNode, int aFirst, + int aLast, MBool& aNonDup) const +{ + NS_ASSERTION(aNode, "missing node in NodeSet::findPosition"); + NS_ASSERTION(aFirst <= aLast+1 && aLast < mElementCount, + "bad position in NodeSet::findPosition"); + + if (aLast - aFirst <= 1) { + // 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]); + if (cmp < 0) { + aNonDup = MB_TRUE; + return pos; + } + + if (cmp == 0) { + aNonDup = MB_FALSE; + return pos; + } + } + + aNonDup = MB_TRUE; + return pos; } -} //-- stringValue + + int midpos = (aFirst + aLast) / 2; + int cmp = aNode->compareDocumentPosition(mElements[midpos]); + if (cmp == 0) { + aNonDup = MB_FALSE; + return midpos; + } + + if (cmp > 0) + return findPosition(aNode, midpos + 1, aLast, aNonDup); + + return findPosition(aNode, aFirst, midpos - 1, aNonDup); +} diff --git a/mozilla/extensions/transformiix/source/xpath/NodeSet.h b/mozilla/extensions/transformiix/source/xpath/NodeSet.h index 9cb790b57a9..970a4e412f0 100644 --- a/mozilla/extensions/transformiix/source/xpath/NodeSet.h +++ b/mozilla/extensions/transformiix/source/xpath/NodeSet.h @@ -1,4 +1,5 @@ -/* +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of @@ -26,218 +27,184 @@ * */ -/** - * NodeSet -**/ +/* + * Implementation of an XPath NodeSet + */ #ifndef TRANSFRMX_NODESET_H #define TRANSFRMX_NODESET_H #include "dom.h" #include "ExprResult.h" +#include "txError.h" class NodeSet : public ExprResult { public: - //----------------/ - //- Constructors -/ - //----------------/ - - /** - * Creates a new NodeSet with the default Size - **/ + /* + * Creates a new empty NodeSet + */ NodeSet(); - /** - * Creates a new NodeSet with the specified Size - **/ - NodeSet(int size); + /* + * Creates a new NodeSet containing the supplied node + */ + NodeSet(Node* aNode); - /** - * Creates a new NodeSet using the given NodeSet - **/ - NodeSet(const NodeSet& source); + /* + * Creates a new NodeSet, copying the Node references from the source + * NodeSet + */ + NodeSet(const NodeSet& aSource); - /** - * Destructor for NodeSet, will not delete Node References - **/ - virtual ~NodeSet(); + /* + * Destructor for NodeSet, will not delete referenced Nodes + */ + virtual ~NodeSet() + { + delete [] mElements; + } - /** - * Adds the specified Node to this NodeSet if it is not already - * contained within in this NodeSet. - * @param node the Node to add to the NodeSet - * @return true if the Node is added to the NodeSet - **/ - MBool add(Node* node); + /* + * 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 add(Node* aNode); - /** - * Adds the specified Node to the NodeSet at the specified index, - * as long as the Node is not already contained within the set - * @param node the Node to add to the NodeSet - * @return true if the Node is added to the NodeSet - * @exception IndexOutOfBoundsException - **/ - MBool add(int index, Node* node); + /* + * 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 NodeSet* aNodes); - /** - * Removes all elements from the list - **/ - void clear(); + /* + * 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. + */ - /** - * Returns true if the specified Node is contained in the set. - * if the specfied Node is null, then if the NodeSet contains a null - * value, true will be returned. - * @param node the element to search the NodeSet for - * @return true if specified Node is contained in the NodeSet - **/ - MBool contains(Node* node); + /* + * 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); - /** - * Copies the elements of this NodeSet, into the destination NodeSet - **/ - void copyInto(NodeSet& dest) const; + /* + * 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 NodeSet* aNodes); - /** - * Returns the Node at the specified position in this NodeSet. - * @param index the position of the Node to return - * @exception IndexOutOfBoundsException - **/ - Node* get(int index); + /* + * Reverse the order of the nodes. + */ + void reverse(); - /** - * Returns true if duplicate checking is enabled, otherwise false. - * - * @return true if duplicate checking is enabled, otherwise false. - **/ - MBool getDuplicateChecking(); + /* + * Removes all nodes from this nodeset + */ + void clear() + { + mElementCount = 0; + } - /** + /* * Returns the index of the specified Node, * or -1 if the Node is not contained in the NodeSet - * @param node the Node to get the index for - **/ - int indexOf(Node* node); + * @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; - /** + /* + * 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 + { + 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 + */ + Node* get(int aIndex) const; + + /* * Returns true if there are no Nodes in the NodeSet. * @return true if there are no Nodes in the NodeSet. - **/ - MBool isEmpty(); + */ + MBool isEmpty() const + { + return mElementCount == 0; + } - /** - * Removes the Node at the specified index from the NodeSet - * @param index the position in the NodeSet to remove the Node from - * @return the Node that was removed from the list - **/ - Node* remove(int index); - - /** - * Removes the the specified Node from the NodeSet - * @param node the Node to remove from the NodeSet - * @return true if the Node was removed from the list - **/ - MBool remove(Node* node); - - /** - * Enables or disables checking for duplicates. By default - * the #add method will check for duplicate nodes. This should - * only be disabled when no possibility of duplicates could occur. - * - * @param checkDuplicates an MBool indicating, when true, to perform duplicate checking, - * otherwise duplicate checking is disabled. - **/ - void setDuplicateChecking(MBool checkDuplicates); - - /** + /* * Returns the number of elements in the NodeSet * @return the number of elements in the NodeSet - **/ - int size() const; + */ + int size() const + { + return mElementCount; + } - /** - * Creates a String representation of this NodeSet - * @param str the destination string to append the String representation to. - **/ - void toString(String& str); - - //------------------------------------/ - //- Virtual Methods from: ExprResult -/ - //------------------------------------/ - - /** - * Returns the type of ExprResult represented - * @return the type of ExprResult represented - **/ - virtual short getResultType(); - - /** - * Converts this ExprResult to a Boolean (MBool) value - * @return the Boolean value - **/ - virtual MBool booleanValue(); - - /** - * Converts this ExprResult to a Number (double) value - * @return the Number value - **/ - virtual double numberValue(); - - /** - * Creates a String representation of this ExprResult - * @param str the destination string to append the String representation to. - **/ - virtual void stringValue(String& str); + /* + * Virtual methods from ExprResult + */ + short getResultType(); + MBool booleanValue(); + double numberValue(); + void stringValue(String& aStr); private: + /* + * 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 ensureSize(int aSize); - //-------------------/ - //- Private Members -/ - //-------------------/ + /* + * 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 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 + */ + MBool findPosition(Node* aNode, int aFirst, int aLast, int& aPos) const; - static const int DEFAULT_SIZE; + Node** mElements; + int mBufferSize; + int mElementCount; - Node** elements; - - int initialSize; - int bufferSize; - - MBool checkDuplicates; - - /** - * The next available location in the elements array - **/ - int elementCount; - - //-------------------/ - //- Private Methods -/ - //-------------------/ - - /** - * Helper method for constructors - **/ - void initialize(int size); - - /** - * increase the NodeSet capacity by a factor of its initial size - **/ - void increaseSize(); - - /** - * Shifts all elements at the specified index to down by 1 - **/ - void shiftDown(int index); - - /** - * Shifts all elements at the specified index up by 1 - **/ - void shiftUp(int index); - -}; //-- NodeSet +}; typedef NodeSet txResultTreeFragment; diff --git a/mozilla/extensions/transformiix/source/xpath/PathExpr.cpp b/mozilla/extensions/transformiix/source/xpath/PathExpr.cpp index 32ed50ae8d6..02ad5dbdac2 100644 --- a/mozilla/extensions/transformiix/source/xpath/PathExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/PathExpr.cpp @@ -96,18 +96,15 @@ void PathExpr::addExpr(Expr* expr, PathOperator pathOp) **/ ExprResult* PathExpr::evaluate(Node* context, ContextState* cs) { - //-- add selectExpr functionality here + if (!context || !expressions.getLength()) + return new StringResult("error"); - if (!context || (expressions.getLength() == 0)) - return new NodeSet(0); - - NodeSet* nodes = new NodeSet(); + NodeSet* nodes = new NodeSet(context); if (!nodes) { // XXX ErrorReport: out of memory NS_ASSERTION(0, "out of memory"); return 0; } - nodes->add(context); ListIterator iter(&expressions); PathExprItem* pxi; @@ -133,7 +130,7 @@ ExprResult* PathExpr::evaluate(Node* context, ContextState* cs) } if (tmpNodes) { - resNodes->copyInto(*tmpNodes); + tmpNodes->add(resNodes); delete resNodes; } else @@ -159,8 +156,9 @@ void PathExpr::evalDescendants (Expr* expr, Node* context, if (!res || (res->getResultType() != ExprResult::NODESET)) { //XXX ErrorReport: report nonnodeset error } - else - ((NodeSet*)res)->copyInto(*resNodes); + else { + resNodes->add((NodeSet*)res); + } delete res; MBool filterWS = cs->isStripSpaceAllowed(context); diff --git a/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp b/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp index 7a83e003e87..689dd3c3a6a 100644 --- a/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp +++ b/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp @@ -64,13 +64,6 @@ void PredicateList::evaluatePredicates(NodeSet* nodes, ContextState* cs) cs->getNodeSetStack()->push(nodes); NodeSet newNodes; - // optimize; set DuplicateChecking to MB_FALSE, - // restore original state later - // we only work with |Node|s already in the NodeSet, so they - // have been checked already, no need to check again in here. - MBool ndsCheckDupl = nodes->getDuplicateChecking(); - nodes->setDuplicateChecking(MB_FALSE); - newNodes.setDuplicateChecking(MB_FALSE); txListIterator iter(&predicates); while (iter.hasNext()) { Expr* expr = (Expr*)iter.next(); @@ -90,23 +83,21 @@ void PredicateList::evaluatePredicates(NodeSet* nodes, ContextState* cs) case ExprResult::NUMBER : // handle default, [position() == numberValue()] if ((double)(nIdx+1) == exprResult->numberValue()) - newNodes.add(node); + newNodes.append(node); break; default: if (exprResult->booleanValue()) - newNodes.add(node); + newNodes.append(node); break; } delete exprResult; } // Move new NodeSet to the current one nodes->clear(); - newNodes.copyInto(*nodes); + nodes->append(&newNodes); } cs->getNodeSetStack()->pop(); - // restore DuplicateChecking of NodeSet - nodes->setDuplicateChecking(ndsCheckDupl); -} // evaluatePredicates +} /* * returns true if this predicate list is empty diff --git a/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp b/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp index cbd6f1a5dce..a7562f6c280 100644 --- a/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp @@ -40,23 +40,14 @@ RootExpr::RootExpr(MBool aSerialize) { * for evaluation * @return the result of the evaluation **/ -ExprResult* RootExpr::evaluate(Node* context, ContextState* cs) { - NodeSet* nodeSet = new NodeSet(); - if (!nodeSet) { - // XXX ErrorReport: out of memory - NS_ASSERTION(0, "out of memory"); - return 0; - } - +ExprResult* RootExpr::evaluate(Node* context, ContextState* cs) +{ if (!context) - return nodeSet; + return new StringResult("error"); if (context->getNodeType() != Node::DOCUMENT_NODE) - nodeSet->add(context->getOwnerDocument()); - else - nodeSet->add(context); - - return nodeSet; + return new NodeSet(context->getOwnerDocument()); + return new NodeSet(context); } //-- evaluate /** diff --git a/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp b/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp index bb250f3db46..eae7a2849c1 100644 --- a/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp @@ -69,22 +69,24 @@ void UnionExpr::addExpr(Expr* expr) { * for evaluation * @return the result of the evaluation **/ -ExprResult* UnionExpr::evaluate(Node* context, ContextState* cs) { - - if (!context || (expressions.getLength() == 0)) - return new NodeSet(0); - +ExprResult* UnionExpr::evaluate(Node* context, ContextState* cs) +{ NodeSet* nodes = new NodeSet(); + if (!context || expressions.getLength() == 0 || !nodes) + return nodes; + txListIterator iter(&expressions); while (iter.hasNext()) { Expr* expr = (Expr*)iter.next(); ExprResult* exprResult = expr->evaluate(context, cs); - if (exprResult && - exprResult->getResultType() == ExprResult::NODESET) { - ((NodeSet*)exprResult)->copyInto(*nodes); + if (!exprResult || + exprResult->getResultType() != ExprResult::NODESET) { + delete exprResult; + return new StringResult("error"); } + nodes->add((NodeSet*)exprResult); delete exprResult; } diff --git a/mozilla/extensions/transformiix/source/xpath/VariableRefExpr.cpp b/mozilla/extensions/transformiix/source/xpath/VariableRefExpr.cpp index 87a3ea977bf..b48da2807b6 100644 --- a/mozilla/extensions/transformiix/source/xpath/VariableRefExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/VariableRefExpr.cpp @@ -59,11 +59,7 @@ ExprResult* VariableRefExpr::evaluate(Node* context, ContextState* cs) { //-- NodeSet case ExprResult::NODESET : { - NodeSet* src = (NodeSet*)exprResult; - NodeSet* dest = new NodeSet(src->size()); - for ( int i = 0; i < src->size(); i++) - dest->add(src->get(i)); - copyOfResult = dest; + copyOfResult = new NodeSet(*(NodeSet*)exprResult); break; } //-- NumberResult @@ -96,4 +92,3 @@ void VariableRefExpr::toString(String& str) { str.append('$'); str.append(name); } //-- toString - diff --git a/mozilla/extensions/transformiix/source/xslt/Numbering.cpp b/mozilla/extensions/transformiix/source/xslt/Numbering.cpp index da9b8fdf811..6b215e7be82 100644 --- a/mozilla/extensions/transformiix/source/xslt/Numbering.cpp +++ b/mozilla/extensions/transformiix/source/xslt/Numbering.cpp @@ -178,7 +178,7 @@ NodeSet* Numbering::getAncestorsOrSelf if ((from) && from->matches(parent, parent->getParentNode(), ps)) break; if (countExpr->matches(parent, parent->getParentNode(), ps)) { - nodeSet->add(parent); + nodeSet->append(parent); if (findNearest) break; } parent = parent->getParentNode(); diff --git a/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp b/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp index 522db857db4..095f67a40b7 100644 --- a/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp +++ b/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp @@ -131,7 +131,7 @@ void ProcessorState::addAttributeSet(Element* aAttributeSet, if (!node->getLocalName(&nodeName) || !nodeName) continue; if (nodeName == txXSLTAtoms::attribute) - attSet->add(node); + attSet->append(node); TX_RELEASE_ATOM(nodeName); } node = node->getNextSibling(); @@ -427,8 +427,6 @@ NodeSet* ProcessorState::getAttributeSet(const String& aName) if (!attset) return attset; - attset->setDuplicateChecking(MB_FALSE); - ImportFrame* frame; txListIterator frameIter(&mImportFrames); frameIter.resetToEnd(); @@ -436,7 +434,7 @@ NodeSet* ProcessorState::getAttributeSet(const String& aName) while ((frame = (ImportFrame*)frameIter.previous())) { NodeSet* nodes = (NodeSet*)frame->mNamedAttributeSets.get(aName); if (nodes) - nodes->copyInto(*attset); + attset->append(nodes); } return attset; } @@ -965,49 +963,6 @@ FunctionCall* ProcessorState::resolveFunctionCall(const String& name) { } //-- resolveFunctionCall - -/** - * Sorts the given NodeSet by DocumentOrder. - * @param nodes the NodeSet to sort - * - * Note: I will be moving this functionality elsewhere soon -**/ -void ProcessorState::sortByDocumentOrder(NodeSet* nodes) { - if (!nodes || (nodes->size() < 2)) - return; - - NodeSet sorted(nodes->size()); - sorted.setDuplicateChecking(MB_FALSE); - sorted.add(nodes->get(0)); - - int i, k; - for (i = 1; i < nodes->size(); i++) { - Node* node = nodes->get(i); - for (k = i - 1; k >= 0; k--) { - Node* tmpNode = sorted.get(k); - if (node->compareDocumentPosition(tmpNode) > 0) { - sorted.add(k + 1, node); - break; - } - else if (k == 0) { - sorted.add(0, node); - break; - } - } - } - - //-- save current state of duplicates checking - MBool checkDuplicates = nodes->getDuplicateChecking(); - nodes->setDuplicateChecking(MB_FALSE); - nodes->clear(); - for (i = 0; i < sorted.size(); i++) { - nodes->add(sorted.get(i)); - } - nodes->setDuplicateChecking(checkDuplicates); - sorted.clear(); - -} //-- sortByDocumentOrder - //-------------------/ //- Private Methods -/ //-------------------/ diff --git a/mozilla/extensions/transformiix/source/xslt/ProcessorState.h b/mozilla/extensions/transformiix/source/xslt/ProcessorState.h index 26278b2386f..bc9f64ee24c 100644 --- a/mozilla/extensions/transformiix/source/xslt/ProcessorState.h +++ b/mozilla/extensions/transformiix/source/xslt/ProcessorState.h @@ -351,14 +351,6 @@ public: **/ virtual FunctionCall* resolveFunctionCall(const String& name); - /** - * Sorts the given NodeSet by DocumentOrder. - * @param nodes the NodeSet to sort - * - * Note: I will be moving this functionality elsewhere soon - **/ - virtual void sortByDocumentOrder(NodeSet* nodes); - /** * Returns the namespace URI for the given namespace prefix. This method * should only be called to get a namespace declared within the diff --git a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp index 5313b37c901..3d8ee4d9ee3 100644 --- a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp +++ b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp @@ -813,8 +813,7 @@ Document* XSLTProcessor::process(Document& xmlDocument, while (iter.hasNext()) ps.addErrorObserver(*(ErrorObserver*)iter.next()); - NodeSet nodeSet; - nodeSet.add(&aXMLDocument); + NodeSet nodeSet(&aXMLDocument); ps.pushCurrentNode(&aXMLDocument); ps.getNodeSetStack()->push(&nodeSet); @@ -864,8 +863,7 @@ void XSLTProcessor::process(Document& aXMLDocument, while (iter.hasNext()) ps.addErrorObserver(*(ErrorObserver*)iter.next()); - NodeSet nodeSet; - nodeSet.add(&aXMLDocument); + NodeSet nodeSet(&aXMLDocument); ps.pushCurrentNode(&aXMLDocument); ps.getNodeSetStack()->push(&nodeSet); @@ -1142,9 +1140,6 @@ void XSLTProcessor::processAction(Node* aNode, if (exprResult->getResultType() == ExprResult::NODESET) { NodeSet* nodeSet = (NodeSet*)exprResult; - //-- make sure nodes are in DocumentOrder - aPs->sortByDocumentOrder(nodeSet); - //-- push nodeSet onto context stack aPs->getNodeSetStack()->push(nodeSet); @@ -1417,9 +1412,6 @@ void XSLTProcessor::processAction(Node* aNode, if (exprResult->getResultType() == ExprResult::NODESET) { NodeSet* nodeSet = (NodeSet*)exprResult; - //-- make sure nodes are in DocumentOrder - aPs->sortByDocumentOrder(nodeSet); - //-- push nodeSet onto context stack aPs->getNodeSetStack()->push(nodeSet); @@ -1917,10 +1909,6 @@ void XSLTProcessor::processDefaultTemplate(Node* node, NodeSet* nodeSet = (NodeSet*)exprResult; - //-- make sure nodes are in DocumentOrder - //-- this isn't strictly neccecary with the current XPath engine - ps->sortByDocumentOrder(nodeSet); - //-- push nodeSet onto context stack ps->getNodeSetStack()->push(nodeSet); for (int i = 0; i < nodeSet->size(); i++) { @@ -2157,7 +2145,6 @@ void XSLTProcessor::xslCopyOf(ExprResult* aExprResult, ProcessorState* aPs) case ExprResult::NODESET: { NodeSet* nodes = (NodeSet*)aExprResult; - aPs->sortByDocumentOrder(nodes); int i; for (i = 0; i < nodes->size(); i++) { Node* node = nodes->get(i); @@ -2348,8 +2335,7 @@ XSLTProcessor::TransformDocument(nsIDOMNode* aSourceDOM, // XXX Need to add error observers // Set current node and nodeset. - NodeSet nodeSet; - nodeSet.add(&sourceDocument); + NodeSet nodeSet(&sourceDocument); ps.pushCurrentNode(&sourceDocument); ps.getNodeSetStack()->push(&nodeSet); diff --git a/mozilla/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp index 5a8a906d7a3..cd9adf74937 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp @@ -22,10 +22,8 @@ CurrentFunctionCall::CurrentFunctionCall(ProcessorState* ps) : * @return the result of the evaluation * @see FunctionCall.h **/ -ExprResult* CurrentFunctionCall::evaluate(Node* context, ContextState* cs) { - - NodeSet* result = new NodeSet(1); - result->add(processorState->getCurrentNode()); - return result; -} //-- evaluate +ExprResult* CurrentFunctionCall::evaluate(Node* context, ContextState* cs) +{ + return new NodeSet(processorState->getCurrentNode()); +} diff --git a/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp index e3a14093c13..e808d6c283d 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp @@ -92,7 +92,6 @@ ExprResult* DocumentFunctionCall::evaluate(Node* context, ContextState* cs) NodeSet* nodeSet2 = (NodeSet*) exprResult2; if (!nodeSet2->isEmpty()) { - mProcessorState->sortByDocumentOrder(nodeSet2); baseURI = nodeSet2->get(0)->getBaseURI(); } delete exprResult2; diff --git a/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp index 3fa3fe8774e..59331770397 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp @@ -81,10 +81,11 @@ ExprResult* GenerateIdFunctionCall::evaluate(Node* aContext, } NodeSet* nodes = (NodeSet*) exprResult; - if (nodes->size() > 0) { - aCs->sortByDocumentOrder(nodes); - node = nodes->get(0); - } + if (nodes->isEmpty()) + return new StringResult(); + + node = nodes->get(0); + delete exprResult; } else { @@ -93,15 +94,10 @@ ExprResult* GenerateIdFunctionCall::evaluate(Node* aContext, // generate id for selected node char buf[22]; - if (node) { #ifdef TX_EXE - sprintf(buf, printfFmt, node); + sprintf(buf, printfFmt, node); #else - PR_snprintf(buf, 21, printfFmt, node); + PR_snprintf(buf, 21, printfFmt, node); #endif - } - else { - buf[0] = 0; - } return new StringResult(buf); } diff --git a/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp index 4c7fdc79a39..0792360cb65 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp @@ -46,15 +46,15 @@ txKeyFunctionCall::txKeyFunctionCall(ProcessorState* aPs) : */ ExprResult* txKeyFunctionCall::evaluate(Node* aContext, ContextState* aCs) { + if (!aContext || !requireParams(2, 2, aCs)) + return new StringResult("error"); + NodeSet* res = new NodeSet; if (!res) { // ErrorReport: out of memory - return NULL; + return 0; } - if (!requireParams(2, 2, aCs)) - return res; - ListIterator iter(¶ms); String keyName; evaluateToString((Expr*)iter.next(), aContext, aCs, keyName); @@ -83,13 +83,13 @@ ExprResult* txKeyFunctionCall::evaluate(Node* aContext, ContextState* aCs) for (int i=0; isize(); i++) { String val; XMLDOMUtils::getNodeValue(nodeSet->get(i), val); - key->getNodes(val,contextDoc)->copyInto(*res); + res->add(key->getNodes(val, contextDoc)); } } else { String val; exprResult->stringValue(val); - key->getNodes(val,contextDoc)->copyInto(*res); + res->append(key->getNodes(val, contextDoc)); } delete exprResult; return res; @@ -227,8 +227,7 @@ void txXSLKey::testNode(Node* aNode, NamedMap* aMap) { Key* key=(Key*)iter.next(); if (key->matchPattern->matches(aNode, 0, mProcessorState)) { - NodeSet contextNodeSet; - contextNodeSet.add(aNode); + NodeSet contextNodeSet(aNode); mProcessorState->getNodeSetStack()->push(&contextNodeSet); mProcessorState->pushCurrentNode(aNode); ExprResult* exprResult = key->useExpr->evaluate(aNode, mProcessorState); @@ -247,7 +246,7 @@ void txXSLKey::testNode(Node* aNode, NamedMap* aMap) return; aMap->put(val, nodeSet); } - nodeSet->add(aNode); + nodeSet->append(aNode); } } else { @@ -259,7 +258,7 @@ void txXSLKey::testNode(Node* aNode, NamedMap* aMap) return; aMap->put(val, nodeSet); } - nodeSet->add(aNode); + nodeSet->append(aNode); } delete exprResult; } diff --git a/mozilla/extensions/transformiix/source/xslt/txRtfHandler.cpp b/mozilla/extensions/transformiix/source/xslt/txRtfHandler.cpp index e93075999e2..0f3b1bff067 100644 --- a/mozilla/extensions/transformiix/source/xslt/txRtfHandler.cpp +++ b/mozilla/extensions/transformiix/source/xslt/txRtfHandler.cpp @@ -54,7 +54,7 @@ txRtfHandler::txRtfHandler(Document* aDocument, DocumentFragment* fragment = mDocument->createDocumentFragment(); NS_ASSERTION(fragment, "Out of memory creating a document fragmen"); // XXX ErrorReport: Out of memory - mResultTreeFragment->add(fragment); + mResultTreeFragment->append(fragment); mCurrentNode = fragment; } diff --git a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp index cccf9e08c8d..1ad4e335420 100644 --- a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp +++ b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp @@ -199,15 +199,13 @@ MBool txNodeSorter::sortNodeSet(NodeSet* aNodes) // Note that the nodeset shouldn't be changed until the sort is done // since it's the current-nodeset used during xpath evaluation aNodes->clear(); - aNodes->setDuplicateChecking(MB_FALSE); iter.reset(); while (iter.hasNext()) { SortableNode* sNode = (SortableNode*)iter.next(); - aNodes->add(sNode->mNode); + aNodes->append(sNode->mNode); sNode->clear(mNKeys); delete sNode; } - aNodes->setDuplicateChecking(MB_TRUE); return MB_TRUE; }