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 TX_XSLT_PATTERNS_H
7 #define TX_XSLT_PATTERNS_H
8 
9 #include "mozilla/Attributes.h"
10 #include "txExpandedName.h"
11 #include "txExpr.h"
12 #include "txXMLUtils.h"
13 
14 class txPattern {
15  public:
16   MOZ_COUNTED_DEFAULT_CTOR(txPattern)
17   MOZ_COUNTED_DTOR_VIRTUAL(txPattern)
18 
19   /*
20    * Determines whether this Pattern matches the given node.
21    */
22   virtual nsresult matches(const txXPathNode& aNode, txIMatchContext* aContext,
23                            bool& aMatched) = 0;
24 
25   /*
26    * Returns the default priority of this Pattern.
27    *
28    * Simple Patterns return the values as specified in XPath 5.5.
29    * Returns -Inf for union patterns, as it shouldn't be called on them.
30    */
31   virtual double getDefaultPriority() = 0;
32 
33   /**
34    * Returns the type of this pattern.
35    */
36   enum Type { STEP_PATTERN, UNION_PATTERN, OTHER_PATTERN };
getType()37   virtual Type getType() { return OTHER_PATTERN; }
38 
39   /**
40    * Returns sub-expression at given position
41    */
42   virtual Expr* getSubExprAt(uint32_t aPos) = 0;
43 
44   /**
45    * Replace sub-expression at given position. Does not delete the old
46    * expression, that is the responsibility of the caller.
47    */
48   virtual void setSubExprAt(uint32_t aPos, Expr* aExpr) = 0;
49 
50   /**
51    * Returns sub-pattern at given position
52    */
53   virtual txPattern* getSubPatternAt(uint32_t aPos) = 0;
54 
55   /**
56    * Replace sub-pattern at given position. Does not delete the old
57    * pattern, that is the responsibility of the caller.
58    */
59   virtual void setSubPatternAt(uint32_t aPos, txPattern* aPattern) = 0;
60 
61 #ifdef TX_TO_STRING
62   /*
63    * Returns the String representation of this Pattern.
64    * @param dest the String to use when creating the String
65    * representation. The String representation will be appended to
66    * any data in the destination String, to allow cascading calls to
67    * other #toString() methods for Patterns.
68    * @return the String representation of this Pattern.
69    */
70   virtual void toString(nsAString& aDest) = 0;
71 #endif
72 };
73 
74 #define TX_DECL_PATTERN_BASE                                            \
75   nsresult matches(const txXPathNode& aNode, txIMatchContext* aContext, \
76                    bool& aMatched) override;                            \
77   double getDefaultPriority() override;                                 \
78   virtual Expr* getSubExprAt(uint32_t aPos) override;                   \
79   virtual void setSubExprAt(uint32_t aPos, Expr* aExpr) override;       \
80   virtual txPattern* getSubPatternAt(uint32_t aPos) override;           \
81   virtual void setSubPatternAt(uint32_t aPos, txPattern* aPattern) override
82 
83 #ifndef TX_TO_STRING
84 #  define TX_DECL_PATTERN TX_DECL_PATTERN_BASE
85 #else
86 #  define TX_DECL_PATTERN \
87     TX_DECL_PATTERN_BASE; \
88     void toString(nsAString& aDest) override
89 #endif
90 
91 #define TX_IMPL_PATTERN_STUBS_NO_SUB_EXPR(_class)               \
92   Expr* _class::getSubExprAt(uint32_t aPos) { return nullptr; } \
93   void _class::setSubExprAt(uint32_t aPos, Expr* aExpr) {       \
94     MOZ_ASSERT_UNREACHABLE("setting bad subexpression index");  \
95   }
96 
97 #define TX_IMPL_PATTERN_STUBS_NO_SUB_PATTERN(_class)                    \
98   txPattern* _class::getSubPatternAt(uint32_t aPos) { return nullptr; } \
99   void _class::setSubPatternAt(uint32_t aPos, txPattern* aPattern) {    \
100     MOZ_ASSERT_UNREACHABLE("setting bad subexpression index");          \
101   }
102 
103 class txUnionPattern : public txPattern {
104  public:
addPattern(txPattern * aPattern)105   void addPattern(txPattern* aPattern) {
106     mLocPathPatterns.AppendElement(aPattern);
107   }
108 
109   TX_DECL_PATTERN;
110   Type getType() override;
111 
112  private:
113   txOwningArray<txPattern> mLocPathPatterns;
114 };
115 
116 class txLocPathPattern : public txPattern {
117  public:
118   void addStep(txPattern* aPattern, bool isChild);
119 
120   TX_DECL_PATTERN;
121 
122  private:
123   class Step {
124    public:
125     mozilla::UniquePtr<txPattern> pattern;
126     bool isChild;
127   };
128 
129   nsTArray<Step> mSteps;
130 };
131 
132 class txRootPattern : public txPattern {
133  public:
134 #ifdef TX_TO_STRING
txRootPattern()135   txRootPattern() : mSerialize(true) {}
136 #endif
137 
138   TX_DECL_PATTERN;
139 
140 #ifdef TX_TO_STRING
141  public:
setSerialize(bool aSerialize)142   void setSerialize(bool aSerialize) { mSerialize = aSerialize; }
143 
144  private:
145   // Don't serialize txRootPattern if it's used in a txLocPathPattern
146   bool mSerialize;
147 #endif
148 };
149 
150 class txIdPattern : public txPattern {
151  public:
152   explicit txIdPattern(const nsAString& aString);
153 
154   TX_DECL_PATTERN;
155 
156  private:
157   nsTArray<RefPtr<nsAtom>> mIds;
158 };
159 
160 class txKeyPattern : public txPattern {
161  public:
txKeyPattern(nsAtom * aPrefix,nsAtom * aLocalName,int32_t aNSID,const nsAString & aValue)162   txKeyPattern(nsAtom* aPrefix, nsAtom* aLocalName, int32_t aNSID,
163                const nsAString& aValue)
164       : mName(aNSID, aLocalName),
165 #ifdef TX_TO_STRING
166         mPrefix(aPrefix),
167 #endif
168         mValue(aValue) {
169   }
170 
171   TX_DECL_PATTERN;
172 
173  private:
174   txExpandedName mName;
175 #ifdef TX_TO_STRING
176   RefPtr<nsAtom> mPrefix;
177 #endif
178   nsString mValue;
179 };
180 
181 class txStepPattern : public txPattern, public PredicateList {
182  public:
txStepPattern(txNodeTest * aNodeTest,bool isAttr)183   txStepPattern(txNodeTest* aNodeTest, bool isAttr)
184       : mNodeTest(aNodeTest), mIsAttr(isAttr) {}
185 
186   TX_DECL_PATTERN;
187   Type getType() override;
188 
getNodeTest()189   txNodeTest* getNodeTest() { return mNodeTest.get(); }
setNodeTest(txNodeTest * aNodeTest)190   void setNodeTest(txNodeTest* aNodeTest) {
191     mozilla::Unused << mNodeTest.release();
192     mNodeTest = mozilla::WrapUnique(aNodeTest);
193   }
194 
195  private:
196   mozilla::UniquePtr<txNodeTest> mNodeTest;
197   bool mIsAttr;
198 };
199 
200 #endif  // TX_XSLT_PATTERNS_H
201