tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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