michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * Implementation of an XPath NodeSet michael@0: */ michael@0: michael@0: #ifndef txNodeSet_h__ michael@0: #define txNodeSet_h__ michael@0: michael@0: #include "txExprResult.h" michael@0: #include "nsError.h" michael@0: #include "txXPathNode.h" michael@0: michael@0: class txNodeSet : public txAExprResult michael@0: { michael@0: public: michael@0: /** michael@0: * Creates a new empty NodeSet michael@0: */ michael@0: txNodeSet(txResultRecycler* aRecycler); michael@0: michael@0: /** michael@0: * Creates a new NodeSet with one node. michael@0: */ michael@0: txNodeSet(const txXPathNode& aNode, txResultRecycler* aRecycler); michael@0: michael@0: /** michael@0: * Creates a new txNodeSet, copying the node references from the source michael@0: * NodeSet. michael@0: */ michael@0: txNodeSet(const txNodeSet& aSource, txResultRecycler* aRecycler); michael@0: michael@0: /** michael@0: * Destructor for txNodeSet, deletes the nodes. michael@0: */ michael@0: virtual ~txNodeSet(); michael@0: michael@0: /** michael@0: * Adds the specified txXPathNode to this NodeSet if it is not already michael@0: * in this NodeSet. The node is inserted according to document order. michael@0: * michael@0: * @param aNode the txXPathNode to add to the NodeSet michael@0: * @return errorcode. michael@0: */ michael@0: nsresult add(const txXPathNode& aNode); michael@0: michael@0: /** michael@0: * Adds the nodes in specified NodeSet to this NodeSet. The resulting michael@0: * NodeSet is sorted in document order and does not contain any duplicate michael@0: * nodes. michael@0: * michael@0: * @param aNodes the NodeSet to add, must be in document order. michael@0: * @return errorcode. michael@0: */ michael@0: nsresult add(const txNodeSet& aNodes); michael@0: nsresult addAndTransfer(txNodeSet* aNodes); michael@0: michael@0: /** michael@0: * Append API michael@0: * These functions should be used with care. michael@0: * They are intended to be used when the caller assures that the resulting michael@0: * NodeSet remains in document order. michael@0: * Abuse will break document order, and cause errors in the result. michael@0: * These functions are significantly faster than the add API, as no michael@0: * order info operations will be performed. michael@0: */ michael@0: michael@0: /** michael@0: * Appends the specified Node to the end of this NodeSet michael@0: * @param aNode the Node to append to the NodeSet michael@0: * @return errorcode. michael@0: */ michael@0: nsresult append(const txXPathNode& aNode); michael@0: michael@0: /** michael@0: * Appends the nodes in the specified NodeSet to the end of this NodeSet michael@0: * @param aNodes the NodeSet to append to the NodeSet michael@0: * @return errorcode. michael@0: */ michael@0: nsresult append(const txNodeSet& aNodes); michael@0: michael@0: /** michael@0: * API to implement reverse axes in LocationStep. michael@0: * michael@0: * Before adding nodes to the nodeset for a reversed axis, call michael@0: * setReverse(). This will make the append(aNode) and get() methods treat michael@0: * the nodeset as required. Do only call append(aNode), get(), mark() michael@0: * and sweep() while the nodeset is reversed. michael@0: * Afterwards, call unsetReverse(). The nodes are stored in document michael@0: * order internally. michael@0: */ michael@0: void setReverse() michael@0: { michael@0: mDirection = -1; michael@0: } michael@0: void unsetReverse() michael@0: { michael@0: mDirection = 1; michael@0: } michael@0: michael@0: /** michael@0: * API to implement predicates in PredicateExpr michael@0: * michael@0: * mark(aIndex) marks the specified member of the nodeset. michael@0: * sweep() clears all members of the nodeset that haven't been michael@0: * marked before and clear the mMarks array. michael@0: */ michael@0: nsresult mark(int32_t aIndex); michael@0: nsresult sweep(); michael@0: michael@0: /** michael@0: * Removes all nodes from this nodeset michael@0: */ michael@0: void clear(); michael@0: michael@0: /** michael@0: * Returns the index of the specified Node, michael@0: * or -1 if the Node is not contained in the NodeSet michael@0: * @param aNode the Node to get the index for michael@0: * @param aStart index to start searching at michael@0: * @return index of specified node or -1 if the node does not exist michael@0: */ michael@0: int32_t indexOf(const txXPathNode& aNode, uint32_t aStart = 0) const; michael@0: michael@0: /** michael@0: * Returns true if the specified Node is contained in the set. michael@0: * @param aNode the Node to search for michael@0: * @return true if specified Node is contained in the NodeSet michael@0: */ michael@0: bool contains(const txXPathNode& aNode) const michael@0: { michael@0: return indexOf(aNode) >= 0; michael@0: } michael@0: michael@0: /** michael@0: * Returns the Node at the specified node in this NodeSet. michael@0: * @param aIndex the node of the Node to return michael@0: * @return Node at specified node michael@0: */ michael@0: const txXPathNode& get(int32_t aIndex) const; michael@0: michael@0: /** michael@0: * Returns true if there are no Nodes in the NodeSet. michael@0: * @return true if there are no Nodes in the NodeSet. michael@0: */ michael@0: bool isEmpty() const michael@0: { michael@0: return mStart ? mStart == mEnd : true; michael@0: } michael@0: michael@0: /** michael@0: * Returns the number of elements in the NodeSet michael@0: * @return the number of elements in the NodeSet michael@0: */ michael@0: int32_t size() const michael@0: { michael@0: return mStart ? mEnd - mStart : 0; michael@0: } michael@0: michael@0: TX_DECL_EXPRRESULT michael@0: michael@0: private: michael@0: /** michael@0: * Ensure that this nodeset can take another aSize nodes. michael@0: * michael@0: * Changes mStart and mEnd as well as mBufferStart and mBufferEnd. michael@0: */ michael@0: bool ensureGrowSize(int32_t aSize); michael@0: michael@0: /** michael@0: * Finds position in the buffer where a node should be inserted michael@0: * to keep the nodeset in document order. Searches the positions michael@0: * aFirst-aLast, including aFirst, but not aLast. michael@0: * @param aNode Node to find insert position for. michael@0: * @param aFirst First item of the search range, included. michael@0: * @param aLast Last item of the search range, excluded. michael@0: * @param aDupe out-param. Will be set to true if the node already michael@0: * exists in the NodeSet, false if it should be michael@0: * inserted. michael@0: * @return pointer where to insert the node. The node should be inserted michael@0: * before the given node. This value is always set, even if aNode michael@0: * already exists in the NodeSet michael@0: */ michael@0: txXPathNode* findPosition(const txXPathNode& aNode, michael@0: txXPathNode* aFirst, michael@0: txXPathNode* aLast, bool& aDupe) const; michael@0: michael@0: static void copyElements(txXPathNode* aDest, const txXPathNode* aStart, michael@0: const txXPathNode* aEnd); michael@0: static void transferElements(txXPathNode* aDest, const txXPathNode* aStart, michael@0: const txXPathNode* aEnd); michael@0: static void destroyElements(const txXPathNode* aStart, michael@0: const txXPathNode* aEnd) michael@0: { michael@0: while (aStart < aEnd) { michael@0: aStart->~txXPathNode(); michael@0: ++aStart; michael@0: } michael@0: } michael@0: michael@0: typedef void (*transferOp) (txXPathNode* aDest, const txXPathNode* aStart, michael@0: const txXPathNode* aEnd); michael@0: typedef void (*destroyOp) (const txXPathNode* aStart, michael@0: const txXPathNode* aEnd); michael@0: nsresult add(const txNodeSet& aNodes, transferOp aTransfer, michael@0: destroyOp aDestroy); michael@0: michael@0: txXPathNode *mStart, *mEnd, *mStartBuffer, *mEndBuffer; michael@0: int32_t mDirection; michael@0: // used for mark() and sweep() in predicates michael@0: bool* mMarks; michael@0: }; michael@0: michael@0: #endif