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