Bumping manifests a=b2g-bump
[gecko.git] / dom / xslt / xpath / txLocationStep.cpp
blob1898ce39b4709da203439d4327af310e5488d68c
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/. */
6 /*
7 Implementation of an XPath LocationStep
8 */
10 #include "txExpr.h"
11 #include "txIXPathContext.h"
12 #include "txNodeSet.h"
13 #include "txXPathTreeWalker.h"
15 //-----------------------------/
16 //- Virtual methods from Expr -/
17 //-----------------------------/
19 /**
20 * Evaluates this Expr based on the given context node and processor state
21 * @param context the context node for evaluation of this Expr
22 * @param ps the ProcessorState containing the stack information needed
23 * for evaluation
24 * @return the result of the evaluation
25 * @see Expr
26 **/
27 nsresult
28 LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
30 NS_ASSERTION(aContext, "internal error");
31 *aResult = nullptr;
33 nsRefPtr<txNodeSet> nodes;
34 nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes));
35 NS_ENSURE_SUCCESS(rv, rv);
37 txXPathTreeWalker walker(aContext->getContextNode());
39 switch (mAxisIdentifier) {
40 case ANCESTOR_AXIS:
42 if (!walker.moveToParent()) {
43 break;
45 // do not break here
47 case ANCESTOR_OR_SELF_AXIS:
49 nodes->setReverse();
51 do {
52 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
53 nodes->append(walker.getCurrentPosition());
55 } while (walker.moveToParent());
57 break;
59 case ATTRIBUTE_AXIS:
61 if (!walker.moveToFirstAttribute()) {
62 break;
65 do {
66 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
67 nodes->append(walker.getCurrentPosition());
69 } while (walker.moveToNextAttribute());
70 break;
72 case DESCENDANT_OR_SELF_AXIS:
74 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
75 nodes->append(walker.getCurrentPosition());
77 // do not break here
79 case DESCENDANT_AXIS:
81 fromDescendants(walker.getCurrentPosition(), aContext, nodes);
82 break;
84 case FOLLOWING_AXIS:
86 if (txXPathNodeUtils::isAttribute(walker.getCurrentPosition())) {
87 walker.moveToParent();
88 fromDescendants(walker.getCurrentPosition(), aContext, nodes);
90 bool cont = true;
91 while (!walker.moveToNextSibling()) {
92 if (!walker.moveToParent()) {
93 cont = false;
94 break;
97 while (cont) {
98 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
99 nodes->append(walker.getCurrentPosition());
102 fromDescendants(walker.getCurrentPosition(), aContext, nodes);
104 while (!walker.moveToNextSibling()) {
105 if (!walker.moveToParent()) {
106 cont = false;
107 break;
111 break;
113 case FOLLOWING_SIBLING_AXIS:
115 while (walker.moveToNextSibling()) {
116 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
117 nodes->append(walker.getCurrentPosition());
120 break;
122 case NAMESPACE_AXIS: //-- not yet implemented
123 #if 0
124 // XXX DEBUG OUTPUT
125 cout << "namespace axis not yet implemented"<<endl;
126 #endif
127 break;
128 case PARENT_AXIS :
130 if (walker.moveToParent() &&
131 mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
132 nodes->append(walker.getCurrentPosition());
134 break;
136 case PRECEDING_AXIS:
138 nodes->setReverse();
140 bool cont = true;
141 while (!walker.moveToPreviousSibling()) {
142 if (!walker.moveToParent()) {
143 cont = false;
144 break;
147 while (cont) {
148 fromDescendantsRev(walker.getCurrentPosition(), aContext, nodes);
150 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
151 nodes->append(walker.getCurrentPosition());
154 while (!walker.moveToPreviousSibling()) {
155 if (!walker.moveToParent()) {
156 cont = false;
157 break;
161 break;
163 case PRECEDING_SIBLING_AXIS:
165 nodes->setReverse();
167 while (walker.moveToPreviousSibling()) {
168 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
169 nodes->append(walker.getCurrentPosition());
172 break;
174 case SELF_AXIS:
176 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
177 nodes->append(walker.getCurrentPosition());
179 break;
181 default: // Children Axis
183 if (!walker.moveToFirstChild()) {
184 break;
187 do {
188 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
189 nodes->append(walker.getCurrentPosition());
191 } while (walker.moveToNextSibling());
192 break;
196 // Apply predicates
197 if (!isEmpty()) {
198 rv = evaluatePredicates(nodes, aContext);
199 NS_ENSURE_SUCCESS(rv, rv);
202 nodes->unsetReverse();
204 NS_ADDREF(*aResult = nodes);
206 return NS_OK;
209 void LocationStep::fromDescendants(const txXPathNode& aNode,
210 txIMatchContext* aCs,
211 txNodeSet* aNodes)
213 txXPathTreeWalker walker(aNode);
214 if (!walker.moveToFirstChild()) {
215 return;
218 do {
219 const txXPathNode& child = walker.getCurrentPosition();
220 if (mNodeTest->matches(child, aCs)) {
221 aNodes->append(child);
223 fromDescendants(child, aCs, aNodes);
224 } while (walker.moveToNextSibling());
227 void LocationStep::fromDescendantsRev(const txXPathNode& aNode,
228 txIMatchContext* aCs,
229 txNodeSet* aNodes)
231 txXPathTreeWalker walker(aNode);
232 if (!walker.moveToLastChild()) {
233 return;
236 do {
237 const txXPathNode& child = walker.getCurrentPosition();
238 fromDescendantsRev(child, aCs, aNodes);
240 if (mNodeTest->matches(child, aCs)) {
241 aNodes->append(child);
244 } while (walker.moveToPreviousSibling());
247 Expr::ExprType
248 LocationStep::getType()
250 return LOCATIONSTEP_EXPR;
254 TX_IMPL_EXPR_STUBS_BASE(LocationStep, NODESET_RESULT)
256 Expr*
257 LocationStep::getSubExprAt(uint32_t aPos)
259 return PredicateList::getSubExprAt(aPos);
262 void
263 LocationStep::setSubExprAt(uint32_t aPos, Expr* aExpr)
265 PredicateList::setSubExprAt(aPos, aExpr);
268 bool
269 LocationStep::isSensitiveTo(ContextSensitivity aContext)
271 return (aContext & NODE_CONTEXT) ||
272 mNodeTest->isSensitiveTo(aContext) ||
273 PredicateList::isSensitiveTo(aContext);
276 #ifdef TX_TO_STRING
277 void
278 LocationStep::toString(nsAString& str)
280 switch (mAxisIdentifier) {
281 case ANCESTOR_AXIS :
282 str.AppendLiteral("ancestor::");
283 break;
284 case ANCESTOR_OR_SELF_AXIS :
285 str.AppendLiteral("ancestor-or-self::");
286 break;
287 case ATTRIBUTE_AXIS:
288 str.Append(char16_t('@'));
289 break;
290 case DESCENDANT_AXIS:
291 str.AppendLiteral("descendant::");
292 break;
293 case DESCENDANT_OR_SELF_AXIS:
294 str.AppendLiteral("descendant-or-self::");
295 break;
296 case FOLLOWING_AXIS :
297 str.AppendLiteral("following::");
298 break;
299 case FOLLOWING_SIBLING_AXIS:
300 str.AppendLiteral("following-sibling::");
301 break;
302 case NAMESPACE_AXIS:
303 str.AppendLiteral("namespace::");
304 break;
305 case PARENT_AXIS :
306 str.AppendLiteral("parent::");
307 break;
308 case PRECEDING_AXIS :
309 str.AppendLiteral("preceding::");
310 break;
311 case PRECEDING_SIBLING_AXIS :
312 str.AppendLiteral("preceding-sibling::");
313 break;
314 case SELF_AXIS :
315 str.AppendLiteral("self::");
316 break;
317 default:
318 break;
320 NS_ASSERTION(mNodeTest, "mNodeTest is null, that's verboten");
321 mNodeTest->toString(str);
323 PredicateList::toString(str);
325 #endif