Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/xslt/xpath/txLocationStep.cpp
Line
Count
Source (jump to first uncovered line)
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 LocationStep
8
*/
9
10
#include "txExpr.h"
11
#include "txIXPathContext.h"
12
#include "txNodeSet.h"
13
#include "txXPathTreeWalker.h"
14
15
  //-----------------------------/
16
 //- Virtual methods from Expr -/
17
//-----------------------------/
18
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)
29
0
{
30
0
    NS_ASSERTION(aContext, "internal error");
31
0
    *aResult = nullptr;
32
0
33
0
    RefPtr<txNodeSet> nodes;
34
0
    nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes));
35
0
    NS_ENSURE_SUCCESS(rv, rv);
36
0
37
0
    txXPathTreeWalker walker(aContext->getContextNode());
38
0
39
0
    switch (mAxisIdentifier) {
40
0
        case ANCESTOR_AXIS:
41
0
        {
42
0
            if (!walker.moveToParent()) {
43
0
                break;
44
0
            }
45
0
            MOZ_FALLTHROUGH;
46
0
        }
47
0
        case ANCESTOR_OR_SELF_AXIS:
48
0
        {
49
0
            nodes->setReverse();
50
0
51
0
            do {
52
0
                rv = appendIfMatching(walker, aContext, nodes);
53
0
                NS_ENSURE_SUCCESS(rv, rv);
54
0
            } while (walker.moveToParent());
55
0
56
0
            break;
57
0
        }
58
0
        case ATTRIBUTE_AXIS:
59
0
        {
60
0
            if (!walker.moveToFirstAttribute()) {
61
0
                break;
62
0
            }
63
0
64
0
            do {
65
0
                rv = appendIfMatching(walker, aContext, nodes);
66
0
                NS_ENSURE_SUCCESS(rv, rv);
67
0
            } while (walker.moveToNextAttribute());
68
0
            break;
69
0
        }
70
0
        case DESCENDANT_OR_SELF_AXIS:
71
0
        {
72
0
            rv = appendIfMatching(walker, aContext, nodes);
73
0
            NS_ENSURE_SUCCESS(rv, rv);
74
0
            MOZ_FALLTHROUGH;
75
0
        }
76
0
        case DESCENDANT_AXIS:
77
0
        {
78
0
            rv = appendMatchingDescendants(walker, aContext, nodes);
79
0
            NS_ENSURE_SUCCESS(rv, rv);
80
0
            break;
81
0
        }
82
0
        case FOLLOWING_AXIS:
83
0
        {
84
0
            if (txXPathNodeUtils::isAttribute(walker.getCurrentPosition())) {
85
0
                walker.moveToParent();
86
0
                rv = appendMatchingDescendants(walker, aContext, nodes);
87
0
                NS_ENSURE_SUCCESS(rv, rv);
88
0
            }
89
0
            bool cont = true;
90
0
            while (!walker.moveToNextSibling()) {
91
0
                if (!walker.moveToParent()) {
92
0
                    cont = false;
93
0
                    break;
94
0
                }
95
0
            }
96
0
            while (cont) {
97
0
                rv = appendIfMatching(walker, aContext, nodes);
98
0
                NS_ENSURE_SUCCESS(rv, rv);
99
0
100
0
                rv = appendMatchingDescendants(walker, aContext, nodes);
101
0
                NS_ENSURE_SUCCESS(rv, rv);
102
0
103
0
                while (!walker.moveToNextSibling()) {
104
0
                    if (!walker.moveToParent()) {
105
0
                        cont = false;
106
0
                        break;
107
0
                    }
108
0
                }
109
0
            }
110
0
            break;
111
0
        }
112
0
        case FOLLOWING_SIBLING_AXIS:
113
0
        {
114
0
            while (walker.moveToNextSibling()) {
115
0
                rv = appendIfMatching(walker, aContext, nodes);
116
0
                NS_ENSURE_SUCCESS(rv, rv);
117
0
            }
118
0
            break;
119
0
        }
120
0
        case NAMESPACE_AXIS: //-- not yet implemented
121
#if 0
122
            // XXX DEBUG OUTPUT
123
            cout << "namespace axis not yet implemented"<<endl;
124
#endif
125
            break;
126
0
        case PARENT_AXIS :
127
0
        {
128
0
            if (walker.moveToParent()) {
129
0
                rv = appendIfMatching(walker, aContext, nodes);
130
0
                NS_ENSURE_SUCCESS(rv, rv);
131
0
            }
132
0
            break;
133
0
        }
134
0
        case PRECEDING_AXIS:
135
0
        {
136
0
            nodes->setReverse();
137
0
138
0
            bool cont = true;
139
0
            while (!walker.moveToPreviousSibling()) {
140
0
                if (!walker.moveToParent()) {
141
0
                    cont = false;
142
0
                    break;
143
0
                }
144
0
            }
145
0
            while (cont) {
146
0
                rv = appendMatchingDescendantsRev(walker, aContext, nodes);
147
0
                NS_ENSURE_SUCCESS(rv, rv);
148
0
149
0
                rv = appendIfMatching(walker, aContext, nodes);
150
0
                NS_ENSURE_SUCCESS(rv, rv);
151
0
152
0
                while (!walker.moveToPreviousSibling()) {
153
0
                    if (!walker.moveToParent()) {
154
0
                        cont = false;
155
0
                        break;
156
0
                    }
157
0
                }
158
0
            }
159
0
            break;
160
0
        }
161
0
        case PRECEDING_SIBLING_AXIS:
162
0
        {
163
0
            nodes->setReverse();
164
0
165
0
            while (walker.moveToPreviousSibling()) {
166
0
                rv = appendIfMatching(walker, aContext, nodes);
167
0
                NS_ENSURE_SUCCESS(rv, rv);
168
0
            }
169
0
            break;
170
0
        }
171
0
        case SELF_AXIS:
172
0
        {
173
0
            rv = appendIfMatching(walker, aContext, nodes);
174
0
            NS_ENSURE_SUCCESS(rv, rv);
175
0
            break;
176
0
        }
177
0
        default: // Children Axis
178
0
        {
179
0
            if (!walker.moveToFirstChild()) {
180
0
                break;
181
0
            }
182
0
183
0
            do {
184
0
                rv = appendIfMatching(walker, aContext, nodes);
185
0
                NS_ENSURE_SUCCESS(rv, rv);
186
0
            } while (walker.moveToNextSibling());
187
0
            break;
188
0
        }
189
0
    }
190
0
191
0
    // Apply predicates
192
0
    if (!isEmpty()) {
193
0
        rv = evaluatePredicates(nodes, aContext);
194
0
        NS_ENSURE_SUCCESS(rv, rv);
195
0
    }
196
0
197
0
    nodes->unsetReverse();
198
0
199
0
    NS_ADDREF(*aResult = nodes);
200
0
201
0
    return NS_OK;
202
0
}
203
204
nsresult
205
LocationStep::appendIfMatching(const txXPathTreeWalker& aWalker,
206
                               txIMatchContext* aContext,
207
                               txNodeSet* aNodes)
208
0
{
209
0
    bool matched;
210
0
    const txXPathNode& child = aWalker.getCurrentPosition();
211
0
    nsresult rv = mNodeTest->matches(child, aContext, matched);
212
0
    NS_ENSURE_SUCCESS(rv, rv);
213
0
214
0
    if (matched) {
215
0
        aNodes->append(child);
216
0
    }
217
0
    return NS_OK;
218
0
}
219
220
nsresult
221
LocationStep::appendMatchingDescendants(const txXPathTreeWalker& aWalker,
222
                                        txIMatchContext* aContext,
223
                                        txNodeSet* aNodes)
224
0
{
225
0
    txXPathTreeWalker walker(aWalker);
226
0
    if (!walker.moveToFirstChild()) {
227
0
        return NS_OK;
228
0
    }
229
0
230
0
    do {
231
0
        nsresult rv = appendIfMatching(walker, aContext, aNodes);
232
0
        NS_ENSURE_SUCCESS(rv, rv);
233
0
234
0
        rv = appendMatchingDescendants(walker, aContext, aNodes);
235
0
        NS_ENSURE_SUCCESS(rv, rv);
236
0
    } while (walker.moveToNextSibling());
237
0
238
0
    return NS_OK;
239
0
}
240
241
nsresult
242
LocationStep::appendMatchingDescendantsRev(const txXPathTreeWalker& aWalker,
243
                                           txIMatchContext* aContext,
244
                                           txNodeSet* aNodes)
245
0
{
246
0
    txXPathTreeWalker walker(aWalker);
247
0
    if (!walker.moveToLastChild()) {
248
0
        return NS_OK;
249
0
    }
250
0
251
0
    do {
252
0
        nsresult rv = appendMatchingDescendantsRev(walker, aContext, aNodes);
253
0
        NS_ENSURE_SUCCESS(rv, rv);
254
0
255
0
        rv = appendIfMatching(walker, aContext, aNodes);
256
0
        NS_ENSURE_SUCCESS(rv, rv);
257
0
    } while (walker.moveToPreviousSibling());
258
0
259
0
    return NS_OK;
260
0
}
261
262
Expr::ExprType
263
LocationStep::getType()
264
0
{
265
0
  return LOCATIONSTEP_EXPR;
266
0
}
267
268
269
TX_IMPL_EXPR_STUBS_BASE(LocationStep, NODESET_RESULT)
270
271
Expr*
272
LocationStep::getSubExprAt(uint32_t aPos)
273
0
{
274
0
    return PredicateList::getSubExprAt(aPos);
275
0
}
276
277
void
278
LocationStep::setSubExprAt(uint32_t aPos, Expr* aExpr)
279
0
{
280
0
    PredicateList::setSubExprAt(aPos, aExpr);
281
0
}
282
283
bool
284
LocationStep::isSensitiveTo(ContextSensitivity aContext)
285
0
{
286
0
    return (aContext & NODE_CONTEXT) ||
287
0
           mNodeTest->isSensitiveTo(aContext) ||
288
0
           PredicateList::isSensitiveTo(aContext);
289
0
}
290
291
#ifdef TX_TO_STRING
292
void
293
LocationStep::toString(nsAString& str)
294
{
295
    switch (mAxisIdentifier) {
296
        case ANCESTOR_AXIS :
297
            str.AppendLiteral("ancestor::");
298
            break;
299
        case ANCESTOR_OR_SELF_AXIS :
300
            str.AppendLiteral("ancestor-or-self::");
301
            break;
302
        case ATTRIBUTE_AXIS:
303
            str.Append(char16_t('@'));
304
            break;
305
        case DESCENDANT_AXIS:
306
            str.AppendLiteral("descendant::");
307
            break;
308
        case DESCENDANT_OR_SELF_AXIS:
309
            str.AppendLiteral("descendant-or-self::");
310
            break;
311
        case FOLLOWING_AXIS :
312
            str.AppendLiteral("following::");
313
            break;
314
        case FOLLOWING_SIBLING_AXIS:
315
            str.AppendLiteral("following-sibling::");
316
            break;
317
        case NAMESPACE_AXIS:
318
            str.AppendLiteral("namespace::");
319
            break;
320
        case PARENT_AXIS :
321
            str.AppendLiteral("parent::");
322
            break;
323
        case PRECEDING_AXIS :
324
            str.AppendLiteral("preceding::");
325
            break;
326
        case PRECEDING_SIBLING_AXIS :
327
            str.AppendLiteral("preceding-sibling::");
328
            break;
329
        case SELF_AXIS :
330
            str.AppendLiteral("self::");
331
            break;
332
        default:
333
            break;
334
    }
335
    NS_ASSERTION(mNodeTest, "mNodeTest is null, that's verboten");
336
    mNodeTest->toString(str);
337
338
    PredicateList::toString(str);
339
}
340
#endif