|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /** |
|
7 * Implementation of an XPath NodeSet |
|
8 */ |
|
9 |
|
10 #ifndef txNodeSet_h__ |
|
11 #define txNodeSet_h__ |
|
12 |
|
13 #include "txExprResult.h" |
|
14 #include "nsError.h" |
|
15 #include "txXPathNode.h" |
|
16 |
|
17 class txNodeSet : public txAExprResult |
|
18 { |
|
19 public: |
|
20 /** |
|
21 * Creates a new empty NodeSet |
|
22 */ |
|
23 txNodeSet(txResultRecycler* aRecycler); |
|
24 |
|
25 /** |
|
26 * Creates a new NodeSet with one node. |
|
27 */ |
|
28 txNodeSet(const txXPathNode& aNode, txResultRecycler* aRecycler); |
|
29 |
|
30 /** |
|
31 * Creates a new txNodeSet, copying the node references from the source |
|
32 * NodeSet. |
|
33 */ |
|
34 txNodeSet(const txNodeSet& aSource, txResultRecycler* aRecycler); |
|
35 |
|
36 /** |
|
37 * Destructor for txNodeSet, deletes the nodes. |
|
38 */ |
|
39 virtual ~txNodeSet(); |
|
40 |
|
41 /** |
|
42 * Adds the specified txXPathNode to this NodeSet if it is not already |
|
43 * in this NodeSet. The node is inserted according to document order. |
|
44 * |
|
45 * @param aNode the txXPathNode to add to the NodeSet |
|
46 * @return errorcode. |
|
47 */ |
|
48 nsresult add(const txXPathNode& aNode); |
|
49 |
|
50 /** |
|
51 * Adds the nodes in specified NodeSet to this NodeSet. The resulting |
|
52 * NodeSet is sorted in document order and does not contain any duplicate |
|
53 * nodes. |
|
54 * |
|
55 * @param aNodes the NodeSet to add, must be in document order. |
|
56 * @return errorcode. |
|
57 */ |
|
58 nsresult add(const txNodeSet& aNodes); |
|
59 nsresult addAndTransfer(txNodeSet* aNodes); |
|
60 |
|
61 /** |
|
62 * Append API |
|
63 * These functions should be used with care. |
|
64 * They are intended to be used when the caller assures that the resulting |
|
65 * NodeSet remains in document order. |
|
66 * Abuse will break document order, and cause errors in the result. |
|
67 * These functions are significantly faster than the add API, as no |
|
68 * order info operations will be performed. |
|
69 */ |
|
70 |
|
71 /** |
|
72 * Appends the specified Node to the end of this NodeSet |
|
73 * @param aNode the Node to append to the NodeSet |
|
74 * @return errorcode. |
|
75 */ |
|
76 nsresult append(const txXPathNode& aNode); |
|
77 |
|
78 /** |
|
79 * Appends the nodes in the specified NodeSet to the end of this NodeSet |
|
80 * @param aNodes the NodeSet to append to the NodeSet |
|
81 * @return errorcode. |
|
82 */ |
|
83 nsresult append(const txNodeSet& aNodes); |
|
84 |
|
85 /** |
|
86 * API to implement reverse axes in LocationStep. |
|
87 * |
|
88 * Before adding nodes to the nodeset for a reversed axis, call |
|
89 * setReverse(). This will make the append(aNode) and get() methods treat |
|
90 * the nodeset as required. Do only call append(aNode), get(), mark() |
|
91 * and sweep() while the nodeset is reversed. |
|
92 * Afterwards, call unsetReverse(). The nodes are stored in document |
|
93 * order internally. |
|
94 */ |
|
95 void setReverse() |
|
96 { |
|
97 mDirection = -1; |
|
98 } |
|
99 void unsetReverse() |
|
100 { |
|
101 mDirection = 1; |
|
102 } |
|
103 |
|
104 /** |
|
105 * API to implement predicates in PredicateExpr |
|
106 * |
|
107 * mark(aIndex) marks the specified member of the nodeset. |
|
108 * sweep() clears all members of the nodeset that haven't been |
|
109 * marked before and clear the mMarks array. |
|
110 */ |
|
111 nsresult mark(int32_t aIndex); |
|
112 nsresult sweep(); |
|
113 |
|
114 /** |
|
115 * Removes all nodes from this nodeset |
|
116 */ |
|
117 void clear(); |
|
118 |
|
119 /** |
|
120 * Returns the index of the specified Node, |
|
121 * or -1 if the Node is not contained in the NodeSet |
|
122 * @param aNode the Node to get the index for |
|
123 * @param aStart index to start searching at |
|
124 * @return index of specified node or -1 if the node does not exist |
|
125 */ |
|
126 int32_t indexOf(const txXPathNode& aNode, uint32_t aStart = 0) const; |
|
127 |
|
128 /** |
|
129 * Returns true if the specified Node is contained in the set. |
|
130 * @param aNode the Node to search for |
|
131 * @return true if specified Node is contained in the NodeSet |
|
132 */ |
|
133 bool contains(const txXPathNode& aNode) const |
|
134 { |
|
135 return indexOf(aNode) >= 0; |
|
136 } |
|
137 |
|
138 /** |
|
139 * Returns the Node at the specified node in this NodeSet. |
|
140 * @param aIndex the node of the Node to return |
|
141 * @return Node at specified node |
|
142 */ |
|
143 const txXPathNode& get(int32_t aIndex) const; |
|
144 |
|
145 /** |
|
146 * Returns true if there are no Nodes in the NodeSet. |
|
147 * @return true if there are no Nodes in the NodeSet. |
|
148 */ |
|
149 bool isEmpty() const |
|
150 { |
|
151 return mStart ? mStart == mEnd : true; |
|
152 } |
|
153 |
|
154 /** |
|
155 * Returns the number of elements in the NodeSet |
|
156 * @return the number of elements in the NodeSet |
|
157 */ |
|
158 int32_t size() const |
|
159 { |
|
160 return mStart ? mEnd - mStart : 0; |
|
161 } |
|
162 |
|
163 TX_DECL_EXPRRESULT |
|
164 |
|
165 private: |
|
166 /** |
|
167 * Ensure that this nodeset can take another aSize nodes. |
|
168 * |
|
169 * Changes mStart and mEnd as well as mBufferStart and mBufferEnd. |
|
170 */ |
|
171 bool ensureGrowSize(int32_t aSize); |
|
172 |
|
173 /** |
|
174 * Finds position in the buffer where a node should be inserted |
|
175 * to keep the nodeset in document order. Searches the positions |
|
176 * aFirst-aLast, including aFirst, but not aLast. |
|
177 * @param aNode Node to find insert position for. |
|
178 * @param aFirst First item of the search range, included. |
|
179 * @param aLast Last item of the search range, excluded. |
|
180 * @param aDupe out-param. Will be set to true if the node already |
|
181 * exists in the NodeSet, false if it should be |
|
182 * inserted. |
|
183 * @return pointer where to insert the node. The node should be inserted |
|
184 * before the given node. This value is always set, even if aNode |
|
185 * already exists in the NodeSet |
|
186 */ |
|
187 txXPathNode* findPosition(const txXPathNode& aNode, |
|
188 txXPathNode* aFirst, |
|
189 txXPathNode* aLast, bool& aDupe) const; |
|
190 |
|
191 static void copyElements(txXPathNode* aDest, const txXPathNode* aStart, |
|
192 const txXPathNode* aEnd); |
|
193 static void transferElements(txXPathNode* aDest, const txXPathNode* aStart, |
|
194 const txXPathNode* aEnd); |
|
195 static void destroyElements(const txXPathNode* aStart, |
|
196 const txXPathNode* aEnd) |
|
197 { |
|
198 while (aStart < aEnd) { |
|
199 aStart->~txXPathNode(); |
|
200 ++aStart; |
|
201 } |
|
202 } |
|
203 |
|
204 typedef void (*transferOp) (txXPathNode* aDest, const txXPathNode* aStart, |
|
205 const txXPathNode* aEnd); |
|
206 typedef void (*destroyOp) (const txXPathNode* aStart, |
|
207 const txXPathNode* aEnd); |
|
208 nsresult add(const txNodeSet& aNodes, transferOp aTransfer, |
|
209 destroyOp aDestroy); |
|
210 |
|
211 txXPathNode *mStart, *mEnd, *mStartBuffer, *mEndBuffer; |
|
212 int32_t mDirection; |
|
213 // used for mark() and sweep() in predicates |
|
214 bool* mMarks; |
|
215 }; |
|
216 |
|
217 #endif |