/src/mozilla-central/dom/xslt/xpath/txExpr.h
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 | | #ifndef TRANSFRMX_EXPR_H |
7 | | #define TRANSFRMX_EXPR_H |
8 | | |
9 | | #include "mozilla/Attributes.h" |
10 | | #include "nsAutoPtr.h" |
11 | | #include "txExprResult.h" |
12 | | #include "txCore.h" |
13 | | #include "nsString.h" |
14 | | #include "txOwningArray.h" |
15 | | #include "nsAtom.h" |
16 | | |
17 | | #ifdef DEBUG |
18 | | #define TX_TO_STRING |
19 | | #endif |
20 | | |
21 | | /* |
22 | | XPath class definitions. |
23 | | Much of this code was ported from XSL:P. |
24 | | */ |
25 | | |
26 | | class nsAtom; |
27 | | class txIMatchContext; |
28 | | class txIEvalContext; |
29 | | class txNodeSet; |
30 | | class txXPathNode; |
31 | | class txXPathTreeWalker; |
32 | | |
33 | | /** |
34 | | * A Base Class for all XSL Expressions |
35 | | **/ |
36 | | class Expr |
37 | | { |
38 | | public: |
39 | | Expr() |
40 | 0 | { |
41 | 0 | MOZ_COUNT_CTOR(Expr); |
42 | 0 | } |
43 | | virtual ~Expr() |
44 | 0 | { |
45 | 0 | MOZ_COUNT_DTOR(Expr); |
46 | 0 | } |
47 | | |
48 | | /** |
49 | | * Evaluates this Expr based on the given context node and processor state |
50 | | * @param context the context node for evaluation of this Expr |
51 | | * @param ps the ContextState containing the stack information needed |
52 | | * for evaluation |
53 | | * @return the result of the evaluation |
54 | | **/ |
55 | | virtual nsresult evaluate(txIEvalContext* aContext, |
56 | | txAExprResult** aResult) = 0; |
57 | | |
58 | | |
59 | | /** |
60 | | * Returns the type of this expression. |
61 | | */ |
62 | | enum ExprType { |
63 | | LOCATIONSTEP_EXPR, |
64 | | PATH_EXPR, |
65 | | UNION_EXPR, |
66 | | LITERAL_EXPR, |
67 | | OTHER_EXPR |
68 | | }; |
69 | | virtual ExprType getType() |
70 | 0 | { |
71 | 0 | return OTHER_EXPR; |
72 | 0 | } |
73 | | |
74 | | /** |
75 | | * Returns the type or types of results this Expr return. |
76 | | */ |
77 | | typedef uint16_t ResultType; |
78 | | enum { |
79 | | NODESET_RESULT = 0x01, |
80 | | BOOLEAN_RESULT = 0x02, |
81 | | NUMBER_RESULT = 0x04, |
82 | | STRING_RESULT = 0x08, |
83 | | RTF_RESULT = 0x10, |
84 | | ANY_RESULT = 0xFFFF |
85 | | }; |
86 | | virtual ResultType getReturnType() = 0; |
87 | | bool canReturnType(ResultType aType) |
88 | 0 | { |
89 | 0 | return (getReturnType() & aType) != 0; |
90 | 0 | } |
91 | | |
92 | | typedef uint16_t ContextSensitivity; |
93 | | enum { |
94 | | NO_CONTEXT = 0x00, |
95 | | NODE_CONTEXT = 0x01, |
96 | | POSITION_CONTEXT = 0x02, |
97 | | SIZE_CONTEXT = 0x04, |
98 | | NODESET_CONTEXT = POSITION_CONTEXT | SIZE_CONTEXT, |
99 | | VARIABLES_CONTEXT = 0x08, |
100 | | PRIVATE_CONTEXT = 0x10, |
101 | | ANY_CONTEXT = 0xFFFF |
102 | | }; |
103 | | |
104 | | /** |
105 | | * Returns true if this expression is sensitive to *any* of |
106 | | * the requested contexts in aContexts. |
107 | | */ |
108 | | virtual bool isSensitiveTo(ContextSensitivity aContexts) = 0; |
109 | | |
110 | | /** |
111 | | * Returns sub-expression at given position |
112 | | */ |
113 | | virtual Expr* getSubExprAt(uint32_t aPos) = 0; |
114 | | |
115 | | /** |
116 | | * Replace sub-expression at given position. Does not delete the old |
117 | | * expression, that is the responsibility of the caller. |
118 | | */ |
119 | | virtual void setSubExprAt(uint32_t aPos, Expr* aExpr) = 0; |
120 | | |
121 | | virtual nsresult evaluateToBool(txIEvalContext* aContext, |
122 | | bool& aResult); |
123 | | |
124 | | virtual nsresult evaluateToString(txIEvalContext* aContext, |
125 | | nsString& aResult); |
126 | | |
127 | | #ifdef TX_TO_STRING |
128 | | /** |
129 | | * Returns the String representation of this Expr. |
130 | | * @param dest the String to use when creating the String |
131 | | * representation. The String representation will be appended to |
132 | | * any data in the destination String, to allow cascading calls to |
133 | | * other #toString() methods for Expressions. |
134 | | * @return the String representation of this Expr. |
135 | | **/ |
136 | | virtual void toString(nsAString& str) = 0; |
137 | | #endif |
138 | | }; //-- Expr |
139 | | |
140 | | #ifdef TX_TO_STRING |
141 | | #define TX_DECL_TOSTRING \ |
142 | | void toString(nsAString& aDest) override; |
143 | | #define TX_DECL_APPENDNAME \ |
144 | | void appendName(nsAString& aDest) override; |
145 | | #else |
146 | | #define TX_DECL_TOSTRING |
147 | | #define TX_DECL_APPENDNAME |
148 | | #endif |
149 | | |
150 | | #define TX_DECL_EXPR_BASE \ |
151 | | nsresult evaluate(txIEvalContext* aContext, txAExprResult** aResult) override; \ |
152 | | ResultType getReturnType() override; \ |
153 | | bool isSensitiveTo(ContextSensitivity aContexts) override; |
154 | | |
155 | | #define TX_DECL_EXPR \ |
156 | | TX_DECL_EXPR_BASE \ |
157 | | TX_DECL_TOSTRING \ |
158 | | Expr* getSubExprAt(uint32_t aPos) override; \ |
159 | | void setSubExprAt(uint32_t aPos, Expr* aExpr) override; |
160 | | |
161 | | #define TX_DECL_OPTIMIZABLE_EXPR \ |
162 | | TX_DECL_EXPR \ |
163 | | ExprType getType() override; |
164 | | |
165 | | #define TX_DECL_FUNCTION \ |
166 | | TX_DECL_APPENDNAME \ |
167 | | TX_DECL_EXPR_BASE |
168 | | |
169 | | #define TX_IMPL_EXPR_STUBS_BASE(_class, _ReturnType) \ |
170 | | Expr::ResultType \ |
171 | 0 | _class::getReturnType() \ |
172 | 0 | { \ |
173 | 0 | return _ReturnType; \ |
174 | 0 | } Unexecuted instantiation: BooleanExpr::getReturnType() Unexecuted instantiation: txErrorExpr::getReturnType() Unexecuted instantiation: FilterExpr::getReturnType() Unexecuted instantiation: LocationStep::getReturnType() Unexecuted instantiation: txNamedAttributeStep::getReturnType() Unexecuted instantiation: txNumberExpr::getReturnType() Unexecuted instantiation: PathExpr::getReturnType() Unexecuted instantiation: RelationalExpr::getReturnType() Unexecuted instantiation: RootExpr::getReturnType() Unexecuted instantiation: UnaryExpr::getReturnType() Unexecuted instantiation: UnionExpr::getReturnType() Unexecuted instantiation: VariableRefExpr::getReturnType() |
175 | | |
176 | | #define TX_IMPL_EXPR_STUBS_0(_class, _ReturnType) \ |
177 | | TX_IMPL_EXPR_STUBS_BASE(_class, _ReturnType) \ |
178 | | Expr* \ |
179 | 0 | _class::getSubExprAt(uint32_t aPos) \ |
180 | 0 | { \ |
181 | 0 | return nullptr; \ |
182 | 0 | } \ Unexecuted instantiation: txErrorExpr::getSubExprAt(unsigned int) Unexecuted instantiation: txNamedAttributeStep::getSubExprAt(unsigned int) Unexecuted instantiation: RootExpr::getSubExprAt(unsigned int) Unexecuted instantiation: VariableRefExpr::getSubExprAt(unsigned int) |
183 | | void \ |
184 | 0 | _class::setSubExprAt(uint32_t aPos, Expr* aExpr) \ |
185 | 0 | { \ |
186 | 0 | MOZ_ASSERT_UNREACHABLE("setting bad subexpression index");\ |
187 | 0 | } Unexecuted instantiation: txErrorExpr::setSubExprAt(unsigned int, Expr*) Unexecuted instantiation: txNamedAttributeStep::setSubExprAt(unsigned int, Expr*) Unexecuted instantiation: RootExpr::setSubExprAt(unsigned int, Expr*) Unexecuted instantiation: VariableRefExpr::setSubExprAt(unsigned int, Expr*) |
188 | | |
189 | | #define TX_IMPL_EXPR_STUBS_1(_class, _ReturnType, _Expr1) \ |
190 | | TX_IMPL_EXPR_STUBS_BASE(_class, _ReturnType) \ |
191 | | Expr* \ |
192 | 0 | _class::getSubExprAt(uint32_t aPos) \ |
193 | 0 | { \ |
194 | 0 | if (aPos == 0) { \ |
195 | 0 | return _Expr1; \ |
196 | 0 | } \ |
197 | 0 | return nullptr; \ |
198 | 0 | } \ |
199 | | void \ |
200 | 0 | _class::setSubExprAt(uint32_t aPos, Expr* aExpr) \ |
201 | 0 | { \ |
202 | 0 | NS_ASSERTION(aPos < 1, "setting bad subexpression index");\ |
203 | 0 | _Expr1.forget(); \ |
204 | 0 | _Expr1 = aExpr; \ |
205 | 0 | } |
206 | | |
207 | | #define TX_IMPL_EXPR_STUBS_2(_class, _ReturnType, _Expr1, _Expr2) \ |
208 | | TX_IMPL_EXPR_STUBS_BASE(_class, _ReturnType) \ |
209 | | Expr* \ |
210 | 0 | _class::getSubExprAt(uint32_t aPos) \ |
211 | 0 | { \ |
212 | 0 | switch(aPos) { \ |
213 | 0 | case 0: \ |
214 | 0 | return _Expr1; \ |
215 | 0 | case 1: \ |
216 | 0 | return _Expr2; \ |
217 | 0 | default: \ |
218 | 0 | break; \ |
219 | 0 | } \ |
220 | 0 | return nullptr; \ |
221 | 0 | } \ Unexecuted instantiation: BooleanExpr::getSubExprAt(unsigned int) Unexecuted instantiation: txNumberExpr::getSubExprAt(unsigned int) Unexecuted instantiation: RelationalExpr::getSubExprAt(unsigned int) |
222 | | void \ |
223 | 0 | _class::setSubExprAt(uint32_t aPos, Expr* aExpr) \ |
224 | 0 | { \ |
225 | 0 | NS_ASSERTION(aPos < 2, "setting bad subexpression index");\ |
226 | 0 | if (aPos == 0) { \ |
227 | 0 | _Expr1.forget(); \ |
228 | 0 | _Expr1 = aExpr; \ |
229 | 0 | } \ |
230 | 0 | else { \ |
231 | 0 | _Expr2.forget(); \ |
232 | 0 | _Expr2 = aExpr; \ |
233 | 0 | } \ |
234 | 0 | } Unexecuted instantiation: BooleanExpr::setSubExprAt(unsigned int, Expr*) Unexecuted instantiation: txNumberExpr::setSubExprAt(unsigned int, Expr*) Unexecuted instantiation: RelationalExpr::setSubExprAt(unsigned int, Expr*) |
235 | | |
236 | | #define TX_IMPL_EXPR_STUBS_LIST(_class, _ReturnType, _ExprList) \ |
237 | | TX_IMPL_EXPR_STUBS_BASE(_class, _ReturnType) \ |
238 | | Expr* \ |
239 | 0 | _class::getSubExprAt(uint32_t aPos) \ |
240 | 0 | { \ |
241 | 0 | return _ExprList.SafeElementAt(aPos); \ |
242 | 0 | } \ |
243 | | void \ |
244 | 0 | _class::setSubExprAt(uint32_t aPos, Expr* aExpr) \ |
245 | 0 | { \ |
246 | 0 | NS_ASSERTION(aPos < _ExprList.Length(), \ |
247 | 0 | "setting bad subexpression index"); \ |
248 | 0 | _ExprList[aPos] = aExpr; \ |
249 | 0 | } |
250 | | |
251 | | |
252 | | /** |
253 | | * This class represents a FunctionCall as defined by the XPath 1.0 |
254 | | * Recommendation. |
255 | | **/ |
256 | | class FunctionCall : public Expr |
257 | | { |
258 | | public: |
259 | | /** |
260 | | * Adds the given parameter to this FunctionCall's parameter list. |
261 | | * The ownership of the given Expr is passed over to the FunctionCall, |
262 | | * even on failure. |
263 | | * @param aExpr the Expr to add to this FunctionCall's parameter list |
264 | | * @return nsresult indicating out of memory |
265 | | */ |
266 | | nsresult addParam(Expr* aExpr) |
267 | 0 | { |
268 | 0 | return mParams.AppendElement(aExpr) ? |
269 | 0 | NS_OK : NS_ERROR_OUT_OF_MEMORY; |
270 | 0 | } |
271 | | |
272 | | /** |
273 | | * Check if the number of parameters falls within a range. |
274 | | * |
275 | | * @param aParamCountMin minimum number of required parameters. |
276 | | * @param aParamCountMax maximum number of parameters. If aParamCountMax |
277 | | * is negative the maximum number is not checked. |
278 | | * @return boolean representing whether the number of parameters falls |
279 | | * within the expected range or not. |
280 | | * |
281 | | * XXX txIEvalContext should be txIParseContest, bug 143291 |
282 | | */ |
283 | | virtual bool requireParams(int32_t aParamCountMin, |
284 | | int32_t aParamCountMax, |
285 | | txIEvalContext* aContext); |
286 | | |
287 | | TX_DECL_TOSTRING |
288 | | Expr* getSubExprAt(uint32_t aPos) override; |
289 | | void setSubExprAt(uint32_t aPos, Expr* aExpr) override; |
290 | | |
291 | | protected: |
292 | | |
293 | | txOwningArray<Expr> mParams; |
294 | | |
295 | | /* |
296 | | * Evaluates the given Expression and converts its result to a number. |
297 | | */ |
298 | | static nsresult evaluateToNumber(Expr* aExpr, txIEvalContext* aContext, |
299 | | double* aResult); |
300 | | |
301 | | /* |
302 | | * Evaluates the given Expression and converts its result to a NodeSet. |
303 | | * If the result is not a NodeSet an error is returned. |
304 | | */ |
305 | | static nsresult evaluateToNodeSet(Expr* aExpr, txIEvalContext* aContext, |
306 | | txNodeSet** aResult); |
307 | | |
308 | | /** |
309 | | * Returns true if any argument is sensitive to the given context. |
310 | | */ |
311 | | bool argsSensitiveTo(ContextSensitivity aContexts); |
312 | | |
313 | | |
314 | | #ifdef TX_TO_STRING |
315 | | /* |
316 | | * Appends the name of the function to `aStr`. |
317 | | */ |
318 | | virtual void appendName(nsAString& aStr) = 0; |
319 | | #endif |
320 | | }; |
321 | | |
322 | | class txCoreFunctionCall : public FunctionCall |
323 | | { |
324 | | public: |
325 | | |
326 | | // This must be ordered in the same order as descriptTable in |
327 | | // txCoreFunctionCall.cpp. If you change one, change the other. |
328 | | enum eType { |
329 | | COUNT = 0, // count() |
330 | | ID, // id() |
331 | | LAST, // last() |
332 | | LOCAL_NAME, // local-name() |
333 | | NAMESPACE_URI, // namespace-uri() |
334 | | NAME, // name() |
335 | | POSITION, // position() |
336 | | |
337 | | CONCAT, // concat() |
338 | | CONTAINS, // contains() |
339 | | NORMALIZE_SPACE, // normalize-space() |
340 | | STARTS_WITH, // starts-with() |
341 | | STRING, // string() |
342 | | STRING_LENGTH, // string-length() |
343 | | SUBSTRING, // substring() |
344 | | SUBSTRING_AFTER, // substring-after() |
345 | | SUBSTRING_BEFORE, // substring-before() |
346 | | TRANSLATE, // translate() |
347 | | |
348 | | NUMBER, // number() |
349 | | ROUND, // round() |
350 | | FLOOR, // floor() |
351 | | CEILING, // ceiling() |
352 | | SUM, // sum() |
353 | | |
354 | | BOOLEAN, // boolean() |
355 | | _FALSE, // false() |
356 | | LANG, // lang() |
357 | | _NOT, // not() |
358 | | _TRUE // true() |
359 | | }; |
360 | | |
361 | | /* |
362 | | * Creates a txCoreFunctionCall of the given type |
363 | | */ |
364 | | explicit txCoreFunctionCall(eType aType) : mType(aType) |
365 | 0 | { |
366 | 0 | } |
367 | | |
368 | | TX_DECL_FUNCTION |
369 | | |
370 | | static bool getTypeFromAtom(nsAtom* aName, eType& aType); |
371 | | |
372 | | private: |
373 | | eType mType; |
374 | | }; |
375 | | |
376 | | |
377 | | /* |
378 | | * This class represents a NodeTest as defined by the XPath spec |
379 | | */ |
380 | | class txNodeTest |
381 | | { |
382 | | public: |
383 | | txNodeTest() |
384 | 0 | { |
385 | 0 | MOZ_COUNT_CTOR(txNodeTest); |
386 | 0 | } |
387 | | virtual ~txNodeTest() |
388 | 0 | { |
389 | 0 | MOZ_COUNT_DTOR(txNodeTest); |
390 | 0 | } |
391 | | |
392 | | /* |
393 | | * Virtual methods |
394 | | * pretty much a txPattern, but not supposed to be used |
395 | | * standalone. The NodeTest node() is different to the |
396 | | * Pattern "node()" (document node isn't matched) |
397 | | */ |
398 | | virtual nsresult matches(const txXPathNode& aNode, |
399 | | txIMatchContext* aContext, |
400 | | bool& aMatched) = 0; |
401 | | virtual double getDefaultPriority() = 0; |
402 | | |
403 | | /** |
404 | | * Returns the type of this nodetest. |
405 | | */ |
406 | | enum NodeTestType { |
407 | | NAME_TEST, |
408 | | NODETYPE_TEST, |
409 | | OTHER_TEST |
410 | | }; |
411 | | virtual NodeTestType getType() |
412 | 0 | { |
413 | 0 | return OTHER_TEST; |
414 | 0 | } |
415 | | |
416 | | /** |
417 | | * Returns true if this expression is sensitive to *any* of |
418 | | * the requested flags. |
419 | | */ |
420 | | virtual bool isSensitiveTo(Expr::ContextSensitivity aContext) = 0; |
421 | | |
422 | | #ifdef TX_TO_STRING |
423 | | virtual void toString(nsAString& aDest) = 0; |
424 | | #endif |
425 | | }; |
426 | | |
427 | | #define TX_DECL_NODE_TEST \ |
428 | | TX_DECL_TOSTRING \ |
429 | | nsresult matches(const txXPathNode& aNode, \ |
430 | | txIMatchContext* aContext, \ |
431 | | bool& aMatched) override; \ |
432 | | double getDefaultPriority() override; \ |
433 | | bool isSensitiveTo(Expr::ContextSensitivity aContext) override; |
434 | | |
435 | | /* |
436 | | * This class represents a NameTest as defined by the XPath spec |
437 | | */ |
438 | | class txNameTest : public txNodeTest |
439 | | { |
440 | | public: |
441 | | /* |
442 | | * Creates a new txNameTest with the given type and the given |
443 | | * principal node type |
444 | | */ |
445 | | txNameTest(nsAtom* aPrefix, nsAtom* aLocalName, int32_t aNSID, |
446 | | uint16_t aNodeType); |
447 | | |
448 | | NodeTestType getType() override; |
449 | | |
450 | | TX_DECL_NODE_TEST |
451 | | |
452 | | RefPtr<nsAtom> mPrefix; |
453 | | RefPtr<nsAtom> mLocalName; |
454 | | int32_t mNamespace; |
455 | | private: |
456 | | uint16_t mNodeType; |
457 | | }; |
458 | | |
459 | | /* |
460 | | * This class represents a NodeType as defined by the XPath spec |
461 | | */ |
462 | | class txNodeTypeTest : public txNodeTest |
463 | | { |
464 | | public: |
465 | | enum NodeType { |
466 | | COMMENT_TYPE, |
467 | | TEXT_TYPE, |
468 | | PI_TYPE, |
469 | | NODE_TYPE |
470 | | }; |
471 | | |
472 | | /* |
473 | | * Creates a new txNodeTypeTest of the given type |
474 | | */ |
475 | | explicit txNodeTypeTest(NodeType aNodeType) |
476 | | : mNodeType(aNodeType) |
477 | 0 | { |
478 | 0 | } |
479 | | |
480 | | /* |
481 | | * Sets the name of the node to match. Only availible for pi nodes |
482 | | */ |
483 | | void setNodeName(const nsAString& aName) |
484 | 0 | { |
485 | 0 | mNodeName = NS_Atomize(aName); |
486 | 0 | } |
487 | | |
488 | | NodeType getNodeTestType() |
489 | 0 | { |
490 | 0 | return mNodeType; |
491 | 0 | } |
492 | | |
493 | | NodeTestType getType() override; |
494 | | |
495 | | TX_DECL_NODE_TEST |
496 | | |
497 | | private: |
498 | | NodeType mNodeType; |
499 | | RefPtr<nsAtom> mNodeName; |
500 | | }; |
501 | | |
502 | | /** |
503 | | * Class representing a nodetest combined with a predicate. May only be used |
504 | | * if the predicate is not sensitive to the context-nodelist. |
505 | | */ |
506 | | class txPredicatedNodeTest : public txNodeTest |
507 | | { |
508 | | public: |
509 | | txPredicatedNodeTest(txNodeTest* aNodeTest, Expr* aPredicate); |
510 | | TX_DECL_NODE_TEST |
511 | | |
512 | | private: |
513 | | nsAutoPtr<txNodeTest> mNodeTest; |
514 | | nsAutoPtr<Expr> mPredicate; |
515 | | }; |
516 | | |
517 | | /** |
518 | | * Represents an ordered list of Predicates, |
519 | | * for use with Step and Filter Expressions |
520 | | **/ |
521 | | class PredicateList { |
522 | | public: |
523 | | /** |
524 | | * Adds the given Expr to the list. |
525 | | * The ownership of the given Expr is passed over the PredicateList, |
526 | | * even on failure. |
527 | | * @param aExpr the Expr to add to the list |
528 | | * @return nsresult indicating out of memory |
529 | | */ |
530 | | nsresult add(Expr* aExpr) |
531 | 0 | { |
532 | 0 | NS_ASSERTION(aExpr, "missing expression"); |
533 | 0 | return mPredicates.AppendElement(aExpr) ? |
534 | 0 | NS_OK : NS_ERROR_OUT_OF_MEMORY; |
535 | 0 | } |
536 | | |
537 | | nsresult evaluatePredicates(txNodeSet* aNodes, txIMatchContext* aContext); |
538 | | |
539 | | /** |
540 | | * Drops the first predicate without deleting it. |
541 | | */ |
542 | | void dropFirst() |
543 | 0 | { |
544 | 0 | mPredicates.RemoveElementAt(0); |
545 | 0 | } |
546 | | |
547 | | /** |
548 | | * returns true if this predicate list is empty |
549 | | **/ |
550 | | bool isEmpty() |
551 | 0 | { |
552 | 0 | return mPredicates.IsEmpty(); |
553 | 0 | } |
554 | | |
555 | | #ifdef TX_TO_STRING |
556 | | /** |
557 | | * Returns the String representation of this PredicateList. |
558 | | * @param dest the String to use when creating the String |
559 | | * representation. The String representation will be appended to |
560 | | * any data in the destination String, to allow cascading calls to |
561 | | * other #toString() methods for Expressions. |
562 | | * @return the String representation of this PredicateList. |
563 | | **/ |
564 | | void toString(nsAString& dest); |
565 | | #endif |
566 | | |
567 | | protected: |
568 | | bool isSensitiveTo(Expr::ContextSensitivity aContext); |
569 | | Expr* getSubExprAt(uint32_t aPos) |
570 | 0 | { |
571 | 0 | return mPredicates.SafeElementAt(aPos); |
572 | 0 | } |
573 | | void setSubExprAt(uint32_t aPos, Expr* aExpr) |
574 | 0 | { |
575 | 0 | NS_ASSERTION(aPos < mPredicates.Length(), |
576 | 0 | "setting bad subexpression index"); |
577 | 0 | mPredicates[aPos] = aExpr; |
578 | 0 | } |
579 | | |
580 | | //-- list of predicates |
581 | | txOwningArray<Expr> mPredicates; |
582 | | }; //-- PredicateList |
583 | | |
584 | | class LocationStep : public Expr, |
585 | | public PredicateList |
586 | | { |
587 | | public: |
588 | | enum LocationStepType { |
589 | | ANCESTOR_AXIS = 0, |
590 | | ANCESTOR_OR_SELF_AXIS, |
591 | | ATTRIBUTE_AXIS, |
592 | | CHILD_AXIS, |
593 | | DESCENDANT_AXIS, |
594 | | DESCENDANT_OR_SELF_AXIS, |
595 | | FOLLOWING_AXIS, |
596 | | FOLLOWING_SIBLING_AXIS, |
597 | | NAMESPACE_AXIS, |
598 | | PARENT_AXIS, |
599 | | PRECEDING_AXIS, |
600 | | PRECEDING_SIBLING_AXIS, |
601 | | SELF_AXIS |
602 | | }; |
603 | | |
604 | | /** |
605 | | * Creates a new LocationStep using the given NodeExpr and Axis Identifier |
606 | | * @param nodeExpr the NodeExpr to use when matching Nodes |
607 | | * @param axisIdentifier the Axis Identifier in which to search for nodes |
608 | | **/ |
609 | | LocationStep(txNodeTest* aNodeTest, |
610 | | LocationStepType aAxisIdentifier) |
611 | | : mNodeTest(aNodeTest), |
612 | | mAxisIdentifier(aAxisIdentifier) |
613 | 0 | { |
614 | 0 | } |
615 | | |
616 | | TX_DECL_OPTIMIZABLE_EXPR |
617 | | |
618 | | txNodeTest* getNodeTest() |
619 | 0 | { |
620 | 0 | return mNodeTest; |
621 | 0 | } |
622 | | void setNodeTest(txNodeTest* aNodeTest) |
623 | 0 | { |
624 | 0 | mNodeTest.forget(); |
625 | 0 | mNodeTest = aNodeTest; |
626 | 0 | } |
627 | | LocationStepType getAxisIdentifier() |
628 | 0 | { |
629 | 0 | return mAxisIdentifier; |
630 | 0 | } |
631 | | void setAxisIdentifier(LocationStepType aAxisIdentifier) |
632 | 0 | { |
633 | 0 | mAxisIdentifier = aAxisIdentifier; |
634 | 0 | } |
635 | | |
636 | | private: |
637 | | /** |
638 | | * Append the current position of aWalker to aNodes if it matches mNodeTest, |
639 | | * using aContext as the context for matching. |
640 | | */ |
641 | | nsresult appendIfMatching(const txXPathTreeWalker& aWalker, |
642 | | txIMatchContext* aContext, |
643 | | txNodeSet* aNodes); |
644 | | |
645 | | /** |
646 | | * Append the descendants of the current position of aWalker to aNodes if |
647 | | * they match mNodeTest, using aContext as the context for matching. |
648 | | */ |
649 | | nsresult appendMatchingDescendants(const txXPathTreeWalker& aWalker, |
650 | | txIMatchContext* aContext, |
651 | | txNodeSet* aNodes); |
652 | | |
653 | | /** |
654 | | * Append the descendants of the current position of aWalker to aNodes in |
655 | | * reverse order if they match mNodeTest, using aContext as the context for |
656 | | * matching. |
657 | | */ |
658 | | nsresult appendMatchingDescendantsRev(const txXPathTreeWalker& aWalker, |
659 | | txIMatchContext* aContext, |
660 | | txNodeSet* aNodes); |
661 | | |
662 | | nsAutoPtr<txNodeTest> mNodeTest; |
663 | | LocationStepType mAxisIdentifier; |
664 | | }; |
665 | | |
666 | | class FilterExpr : public Expr, |
667 | | public PredicateList |
668 | | { |
669 | | public: |
670 | | |
671 | | /** |
672 | | * Creates a new FilterExpr using the given Expr |
673 | | * @param expr the Expr to use for evaluation |
674 | | */ |
675 | | explicit FilterExpr(Expr* aExpr) |
676 | | : expr(aExpr) |
677 | 0 | { |
678 | 0 | } |
679 | | |
680 | | TX_DECL_EXPR |
681 | | |
682 | | private: |
683 | | nsAutoPtr<Expr> expr; |
684 | | |
685 | | }; //-- FilterExpr |
686 | | |
687 | | |
688 | | class txLiteralExpr : public Expr { |
689 | | public: |
690 | | explicit txLiteralExpr(double aDbl) |
691 | | : mValue(new NumberResult(aDbl, nullptr)) |
692 | 0 | { |
693 | 0 | } |
694 | | explicit txLiteralExpr(const nsAString& aStr) |
695 | | : mValue(new StringResult(aStr, nullptr)) |
696 | 0 | { |
697 | 0 | } |
698 | | explicit txLiteralExpr(txAExprResult* aValue) |
699 | | : mValue(aValue) |
700 | 0 | { |
701 | 0 | } |
702 | | |
703 | | TX_DECL_EXPR |
704 | | |
705 | | private: |
706 | | RefPtr<txAExprResult> mValue; |
707 | | }; |
708 | | |
709 | | /** |
710 | | * Represents an UnaryExpr. Returns the negative value of its expr. |
711 | | **/ |
712 | | class UnaryExpr : public Expr { |
713 | | |
714 | | public: |
715 | | |
716 | | explicit UnaryExpr(Expr* aExpr) |
717 | | : expr(aExpr) |
718 | 0 | { |
719 | 0 | } |
720 | | |
721 | | TX_DECL_EXPR |
722 | | |
723 | | private: |
724 | | nsAutoPtr<Expr> expr; |
725 | | }; //-- UnaryExpr |
726 | | |
727 | | /** |
728 | | * Represents a BooleanExpr, a binary expression that |
729 | | * performs a boolean operation between its lvalue and rvalue. |
730 | | **/ |
731 | | class BooleanExpr : public Expr |
732 | | { |
733 | | public: |
734 | | |
735 | | //-- BooleanExpr Types |
736 | | enum _BooleanExprType { AND = 1, OR }; |
737 | | |
738 | | BooleanExpr(Expr* aLeftExpr, Expr* aRightExpr, short aOp) |
739 | | : leftExpr(aLeftExpr), |
740 | | rightExpr(aRightExpr), |
741 | | op(aOp) |
742 | 0 | { |
743 | 0 | } |
744 | | |
745 | | TX_DECL_EXPR |
746 | | |
747 | | private: |
748 | | nsAutoPtr<Expr> leftExpr, rightExpr; |
749 | | short op; |
750 | | }; //-- BooleanExpr |
751 | | |
752 | | /** |
753 | | * Represents a MultiplicativeExpr, a binary expression that |
754 | | * performs a multiplicative operation between its lvalue and rvalue: |
755 | | * * : multiply |
756 | | * mod : modulus |
757 | | * div : divide |
758 | | * |
759 | | **/ |
760 | | class txNumberExpr : public Expr |
761 | | { |
762 | | public: |
763 | | |
764 | | enum eOp { ADD, SUBTRACT, DIVIDE, MULTIPLY, MODULUS }; |
765 | | |
766 | | txNumberExpr(Expr* aLeftExpr, Expr* aRightExpr, eOp aOp) |
767 | | : mLeftExpr(aLeftExpr), |
768 | | mRightExpr(aRightExpr), |
769 | | mOp(aOp) |
770 | 0 | { |
771 | 0 | } |
772 | | |
773 | | TX_DECL_EXPR |
774 | | |
775 | | private: |
776 | | nsAutoPtr<Expr> mLeftExpr, mRightExpr; |
777 | | eOp mOp; |
778 | | }; //-- MultiplicativeExpr |
779 | | |
780 | | /** |
781 | | * Represents a RelationalExpr, an expression that compares its lvalue |
782 | | * to its rvalue using: |
783 | | * = : equal to |
784 | | * < : less than |
785 | | * > : greater than |
786 | | * <= : less than or equal to |
787 | | * >= : greater than or equal to |
788 | | * |
789 | | **/ |
790 | | class RelationalExpr : public Expr |
791 | | { |
792 | | public: |
793 | | enum RelationalExprType { |
794 | | EQUAL, |
795 | | NOT_EQUAL, |
796 | | LESS_THAN, |
797 | | GREATER_THAN, |
798 | | LESS_OR_EQUAL, |
799 | | GREATER_OR_EQUAL |
800 | | }; |
801 | | |
802 | | RelationalExpr(Expr* aLeftExpr, Expr* aRightExpr, RelationalExprType aOp) |
803 | | : mLeftExpr(aLeftExpr), |
804 | | mRightExpr(aRightExpr), |
805 | | mOp(aOp) |
806 | 0 | { |
807 | 0 | } |
808 | | |
809 | | |
810 | | TX_DECL_EXPR |
811 | | |
812 | | private: |
813 | | bool compareResults(txIEvalContext* aContext, txAExprResult* aLeft, |
814 | | txAExprResult* aRight); |
815 | | |
816 | | nsAutoPtr<Expr> mLeftExpr; |
817 | | nsAutoPtr<Expr> mRightExpr; |
818 | | RelationalExprType mOp; |
819 | | }; |
820 | | |
821 | | /** |
822 | | * VariableRefExpr |
823 | | * Represents a variable reference ($refname) |
824 | | **/ |
825 | | class VariableRefExpr : public Expr { |
826 | | |
827 | | public: |
828 | | |
829 | | VariableRefExpr(nsAtom* aPrefix, nsAtom* aLocalName, int32_t aNSID); |
830 | | |
831 | | TX_DECL_EXPR |
832 | | |
833 | | private: |
834 | | RefPtr<nsAtom> mPrefix; |
835 | | RefPtr<nsAtom> mLocalName; |
836 | | int32_t mNamespace; |
837 | | }; |
838 | | |
839 | | /** |
840 | | * Represents a PathExpr |
841 | | **/ |
842 | | class PathExpr : public Expr { |
843 | | |
844 | | public: |
845 | | |
846 | | //-- Path Operators |
847 | | //-- RELATIVE_OP is the default |
848 | | //-- LF, changed from static const short to enum |
849 | | enum PathOperator { RELATIVE_OP, DESCENDANT_OP }; |
850 | | |
851 | | /** |
852 | | * Adds the Expr to this PathExpr |
853 | | * The ownership of the given Expr is passed over the PathExpr, |
854 | | * even on failure. |
855 | | * @param aExpr the Expr to add to this PathExpr |
856 | | * @return nsresult indicating out of memory |
857 | | */ |
858 | | nsresult addExpr(Expr* aExpr, PathOperator pathOp); |
859 | | |
860 | | /** |
861 | | * Removes and deletes the expression at the given index. |
862 | | */ |
863 | | void deleteExprAt(uint32_t aPos) |
864 | 0 | { |
865 | 0 | NS_ASSERTION(aPos < mItems.Length(), |
866 | 0 | "killing bad expression index"); |
867 | 0 | mItems.RemoveElementAt(aPos); |
868 | 0 | } |
869 | | |
870 | | TX_DECL_OPTIMIZABLE_EXPR |
871 | | |
872 | | PathOperator getPathOpAt(uint32_t aPos) |
873 | 0 | { |
874 | 0 | NS_ASSERTION(aPos < mItems.Length(), "getting bad pathop index"); |
875 | 0 | return mItems[aPos].pathOp; |
876 | 0 | } |
877 | | void setPathOpAt(uint32_t aPos, PathOperator aPathOp) |
878 | 0 | { |
879 | 0 | NS_ASSERTION(aPos < mItems.Length(), "setting bad pathop index"); |
880 | 0 | mItems[aPos].pathOp = aPathOp; |
881 | 0 | } |
882 | | |
883 | | private: |
884 | | class PathExprItem { |
885 | | public: |
886 | | nsAutoPtr<Expr> expr; |
887 | | PathOperator pathOp; |
888 | | }; |
889 | | |
890 | | nsTArray<PathExprItem> mItems; |
891 | | |
892 | | /* |
893 | | * Selects from the descendants of the context node |
894 | | * all nodes that match the Expr |
895 | | */ |
896 | | nsresult evalDescendants(Expr* aStep, const txXPathNode& aNode, |
897 | | txIMatchContext* aContext, |
898 | | txNodeSet* resNodes); |
899 | | }; |
900 | | |
901 | | /** |
902 | | * This class represents a RootExpr, which only matches the Document node |
903 | | **/ |
904 | | class RootExpr : public Expr { |
905 | | public: |
906 | | /** |
907 | | * Creates a new RootExpr |
908 | | */ |
909 | | RootExpr() |
910 | | #ifdef TX_TO_STRING |
911 | | : mSerialize(true) |
912 | | #endif |
913 | 0 | { |
914 | 0 | } |
915 | | |
916 | | TX_DECL_EXPR |
917 | | |
918 | | #ifdef TX_TO_STRING |
919 | | public: |
920 | | void setSerialize(bool aSerialize) |
921 | | { |
922 | | mSerialize = aSerialize; |
923 | | } |
924 | | |
925 | | private: |
926 | | // When a RootExpr is used in a PathExpr it shouldn't be serialized |
927 | | bool mSerialize; |
928 | | #endif |
929 | | }; //-- RootExpr |
930 | | |
931 | | /** |
932 | | * Represents a UnionExpr |
933 | | **/ |
934 | | class UnionExpr : public Expr { |
935 | | public: |
936 | | /** |
937 | | * Adds the PathExpr to this UnionExpr |
938 | | * The ownership of the given Expr is passed over the UnionExpr, |
939 | | * even on failure. |
940 | | * @param aExpr the Expr to add to this UnionExpr |
941 | | * @return nsresult indicating out of memory |
942 | | */ |
943 | | nsresult addExpr(Expr* aExpr) |
944 | 0 | { |
945 | 0 | return mExpressions.AppendElement(aExpr) ? |
946 | 0 | NS_OK : NS_ERROR_OUT_OF_MEMORY; |
947 | 0 | } |
948 | | |
949 | | /** |
950 | | * Removes and deletes the expression at the given index. |
951 | | */ |
952 | | void deleteExprAt(uint32_t aPos) |
953 | 0 | { |
954 | 0 | NS_ASSERTION(aPos < mExpressions.Length(), |
955 | 0 | "killing bad expression index"); |
956 | 0 |
|
957 | 0 | delete mExpressions[aPos]; |
958 | 0 | mExpressions.RemoveElementAt(aPos); |
959 | 0 | } |
960 | | |
961 | | TX_DECL_OPTIMIZABLE_EXPR |
962 | | |
963 | | private: |
964 | | |
965 | | txOwningArray<Expr> mExpressions; |
966 | | |
967 | | }; //-- UnionExpr |
968 | | |
969 | | /** |
970 | | * Class specializing in executing expressions like "@foo" where we are |
971 | | * interested in different result-types, and expressions like "@foo = 'hi'" |
972 | | */ |
973 | | class txNamedAttributeStep : public Expr |
974 | | { |
975 | | public: |
976 | | txNamedAttributeStep(int32_t aNsID, nsAtom* aPrefix, |
977 | | nsAtom* aLocalName); |
978 | | |
979 | | TX_DECL_EXPR |
980 | | |
981 | | private: |
982 | | int32_t mNamespace; |
983 | | RefPtr<nsAtom> mPrefix; |
984 | | RefPtr<nsAtom> mLocalName; |
985 | | }; |
986 | | |
987 | | /** |
988 | | * |
989 | | */ |
990 | | class txUnionNodeTest : public txNodeTest |
991 | | { |
992 | | public: |
993 | | nsresult addNodeTest(txNodeTest* aNodeTest) |
994 | 0 | { |
995 | 0 | return mNodeTests.AppendElement(aNodeTest) ? |
996 | 0 | NS_OK : NS_ERROR_OUT_OF_MEMORY; |
997 | 0 | } |
998 | | |
999 | | TX_DECL_NODE_TEST |
1000 | | |
1001 | | private: |
1002 | | txOwningArray<txNodeTest> mNodeTests; |
1003 | | }; |
1004 | | |
1005 | | /** |
1006 | | * Expression that failed to parse |
1007 | | */ |
1008 | | class txErrorExpr : public Expr |
1009 | | { |
1010 | | public: |
1011 | | #ifdef TX_TO_STRING |
1012 | | explicit txErrorExpr(const nsAString& aStr) |
1013 | | : mStr(aStr) |
1014 | | { |
1015 | | } |
1016 | | #endif |
1017 | | |
1018 | | TX_DECL_EXPR |
1019 | | |
1020 | | #ifdef TX_TO_STRING |
1021 | | private: |
1022 | | nsString mStr; |
1023 | | #endif |
1024 | | }; |
1025 | | |
1026 | | #endif |
1027 | | |
1028 | | |