Initial commit
[profile/ivi/openjade.git] / style / Pattern.h
1 // Copyright (c) 1997 James Clark
2 // See the file copying.txt for copying permission.
3
4 #ifndef Pattern_INCLUDED
5 #define Pattern_INCLUDED 1
6
7 #include "Boolean.h"
8 #include "Node.h"
9 #include "Link.h"
10 #include "IList.h"
11 #include "IListIter.h"
12 #include "StringC.h"
13 #include "Vector.h"
14 #include "Ptr.h"
15 #include "Resource.h"
16
17 #ifdef DSSSL_NAMESPACE
18 namespace DSSSL_NAMESPACE {
19 #endif
20
21 class Pattern {
22 public:
23   class MatchContext : public SdataMapper {
24   public:
25     const Vector<StringC> &classAttributeNames() const;
26     const Vector<StringC> &idAttributeNames() const;
27   protected:
28     Vector<StringC> classAttributeNames_;
29     Vector<StringC> idAttributeNames_;
30   };
31   class Qualifier : public Link {
32   public:
33     virtual ~Qualifier();
34     virtual bool satisfies(const NodePtr &, MatchContext &) const = 0;
35     virtual void contributeSpecificity(int *) const = 0;
36     virtual bool vacuous() const;
37   protected:
38     static bool matchAttribute(const StringC &name,
39                                const StringC &value,
40                                const NodePtr &nd,
41                                MatchContext &context);
42   };
43   class IdQualifier : public Qualifier {
44   public:
45     IdQualifier(const StringC &);
46     bool satisfies(const NodePtr &, MatchContext &) const;
47     void contributeSpecificity(int *) const;
48   private:
49     StringC id_;
50   };
51   class ClassQualifier : public Qualifier {
52   public:
53     ClassQualifier(const StringC &);
54     bool satisfies(const NodePtr &, MatchContext &) const;
55     void contributeSpecificity(int *) const;
56   private:
57     StringC class_;
58   };
59   class AttributeHasValueQualifier : public Qualifier {
60   public:
61     AttributeHasValueQualifier(const StringC &);
62     bool satisfies(const NodePtr &, MatchContext &) const;
63     void contributeSpecificity(int *) const;
64   private:
65     StringC name_;
66   };
67   class AttributeMissingValueQualifier : public Qualifier {
68   public:
69     AttributeMissingValueQualifier(const StringC &);
70     bool satisfies(const NodePtr &, MatchContext &) const;
71     void contributeSpecificity(int *) const;
72   private:
73     StringC name_;
74   };
75   class AttributeQualifier : public Qualifier {
76   public:
77     AttributeQualifier(const StringC &, const StringC &);
78     bool satisfies(const NodePtr &, MatchContext &) const;
79     void contributeSpecificity(int *) const;
80   private:
81     StringC name_;
82     StringC value_;
83   };
84   class PositionQualifier : public Qualifier {
85   public:
86     void contributeSpecificity(int *) const;
87   };
88   class FirstOfTypeQualifier : public PositionQualifier {
89   public:
90     bool satisfies(const NodePtr &, MatchContext &) const;
91   };
92   class LastOfTypeQualifier : public PositionQualifier {
93   public:
94     bool satisfies(const NodePtr &, MatchContext &) const;
95   };
96   class FirstOfAnyQualifier : public PositionQualifier {
97   public:
98     bool satisfies(const NodePtr &, MatchContext &) const;
99   };
100   class LastOfAnyQualifier : public PositionQualifier {
101   public:
102     bool satisfies(const NodePtr &, MatchContext &) const;
103   };
104   class OnlyQualifier : public Qualifier {
105   public:
106     void contributeSpecificity(int *) const;
107   };
108   class OnlyOfTypeQualifier : public OnlyQualifier {
109   public:
110     bool satisfies(const NodePtr &, MatchContext &) const;
111   };
112   class OnlyOfAnyQualifier : public OnlyQualifier {
113   public:
114     bool satisfies(const NodePtr &, MatchContext &) const;
115   };
116   class VacuousQualifier : public Qualifier {
117   public:
118     bool vacuous() const;
119   };
120   class PriorityQualifier : public VacuousQualifier {
121   public:
122     PriorityQualifier(long);
123     void contributeSpecificity(int *) const;
124     bool satisfies(const NodePtr &, MatchContext &) const;
125   private:
126     long n_;
127   };
128   class ImportanceQualifier : public VacuousQualifier {
129   public:
130     ImportanceQualifier(long);
131     void contributeSpecificity(int *) const;
132     bool satisfies(const NodePtr &, MatchContext &) const;
133   private:
134     long n_;
135   };
136   typedef unsigned Repeat;
137   class Element : public Link {
138   public:
139     Element(const StringC &);
140     bool matches(const NodePtr &, MatchContext &) const;
141     void contributeSpecificity(int *) const;
142     void addQualifier(Qualifier *);
143     void setRepeat(Repeat minRepeat, Repeat maxRepeat);
144     Repeat minRepeat() const;
145     Repeat maxRepeat() const;
146     bool mustHaveGi(StringC &) const;
147     bool trivial() const;
148   private:
149     StringC gi_;
150     Repeat minRepeat_;
151     Repeat maxRepeat_;
152     IList<Qualifier> qualifiers_;
153   };
154   class ChildrenQualifier : public Qualifier {
155   public:
156     ChildrenQualifier(IList<Element> &);
157     bool satisfies(const NodePtr &, MatchContext &) const;
158     void contributeSpecificity(int *) const;
159   private:
160     IList<Element> children_;
161   };
162   Pattern();
163   Pattern(IList<Element> &);
164   void swap(Pattern &);
165   bool matches(const NodePtr &, MatchContext &) const;
166   // If mustHaveGi returns true, then any element that matches the pattern
167   // must have the string returned in str.
168   bool mustHaveGi(StringC &str) const;
169   // A pattern is trivial if any element that has the gi returned my mustHaveGi
170   // matches the pattern, or, if mustHaveGi returns false, if any element matches
171   // the pattern.
172   bool trivial() const;
173   static int compareSpecificity(const Pattern &, const Pattern &);
174   enum {
175     importanceSpecificity,
176     idSpecificity,
177     classSpecificity,
178     giSpecificity,
179     repeatSpecificity,
180     prioritySpecificity,
181     onlySpecificity,
182     positionSpecificity,
183     attributeSpecificity,
184     nSpecificity
185   };
186 private:
187   Pattern(const Pattern &);     // undefined
188   void operator=(const Pattern &); // undefined
189   void computeSpecificity(int *) const;
190   static bool computeTrivial(const IList<Element> &);
191
192   static bool matchAncestors(const IListIter<Element> &,
193                              const NodePtr &,
194                              MatchContext &);
195   static bool matchAncestors1(const IListIter<Element> &,
196                               const NodePtr &,
197                               MatchContext &);
198
199   IList<Element> ancestors_; // first is self, second is parent ...
200   bool trivial_;
201 };
202
203 inline
204 void Pattern::Element::setRepeat(Repeat minRepeat, Repeat maxRepeat)
205 {
206   minRepeat_ = minRepeat;
207   maxRepeat_ = maxRepeat;
208 }
209
210 inline
211 Pattern::Repeat Pattern::Element::minRepeat() const
212 {
213   return minRepeat_;
214 }
215
216 inline
217 Pattern::Repeat Pattern::Element::maxRepeat() const
218 {
219   return maxRepeat_;
220 }
221
222 inline
223 void Pattern::Element::addQualifier(Qualifier *q)
224 {
225   qualifiers_.insert(q);
226 }
227
228 inline
229 bool Pattern::matchAncestors(const IListIter<Element> &ancestors,
230                              const NodePtr &node,
231                              MatchContext &context)
232 {
233   return ancestors.done() || matchAncestors1(ancestors, node, context);
234 }
235
236 inline
237 bool Pattern::matches(const NodePtr &nd, MatchContext &context) const
238 {
239   return matchAncestors(IListIter<Element>(ancestors_),
240                         nd,
241                         context);
242 }
243
244 inline
245 void Pattern::swap(Pattern &pattern)
246 {
247   ancestors_.swap(pattern.ancestors_);
248   bool tem = trivial_;
249   trivial_ = pattern.trivial_;
250   pattern.trivial_ = tem;
251 }
252
253 inline
254 bool Pattern::Element::mustHaveGi(StringC &gi) const
255 {
256   if (minRepeat_ == 0)
257     return 0;
258   else if (gi_.size()) {
259     gi = gi_;
260     return 1;
261   }
262   else
263     return 0;
264 }
265
266 inline
267 bool Pattern::mustHaveGi(StringC &gi) const
268 {
269   return !ancestors_.empty() && ancestors_.head()->mustHaveGi(gi);
270 }
271
272 inline
273 const Vector<StringC> &Pattern::MatchContext::classAttributeNames() const
274 {
275   return classAttributeNames_;
276 }
277
278 inline
279 const Vector<StringC> &Pattern::MatchContext::idAttributeNames() const
280 {
281   return idAttributeNames_;
282 }
283
284 inline
285 bool Pattern::trivial() const
286 {
287   return trivial_;
288 }
289
290 #ifdef DSSSL_NAMESPACE
291 }
292 #endif
293
294 #endif /* not Pattern_INCLUDED */