1 // sass.hpp must go before all system headers to get the
2 // __EXTENSIONS__ fix on Solaris.
3 #include "sass.hpp"
4 
5 #include "ast_selectors.hpp"
6 
7 namespace Sass {
8 
9   /*#########################################################################*/
10   // Compare against base class on right hand side
11   // try to find the most specialized implementation
12   /*#########################################################################*/
13 
14   // Selector lists can be compared to comma lists
operator ==(const Expression & rhs) const15   bool SelectorList::operator== (const Expression& rhs) const
16   {
17     if (auto l = Cast<List>(&rhs)) { return *this == *l; }
18     if (auto s = Cast<Selector>(&rhs)) { return *this == *s; }
19     if (Cast<String>(&rhs) || Cast<Null>(&rhs)) { return false; }
20     throw std::runtime_error("invalid selector base classes to compare");
21   }
22 
23   // Selector lists can be compared to comma lists
operator ==(const Selector & rhs) const24   bool SelectorList::operator== (const Selector& rhs) const
25   {
26     if (auto sel = Cast<SelectorList>(&rhs)) { return *this == *sel; }
27     if (auto sel = Cast<ComplexSelector>(&rhs)) { return *this == *sel; }
28     if (auto sel = Cast<CompoundSelector>(&rhs)) { return *this == *sel; }
29     if (auto sel = Cast<SimpleSelector>(&rhs)) { return *this == *sel; }
30     if (auto list = Cast<List>(&rhs)) { return *this == *list; }
31     throw std::runtime_error("invalid selector base classes to compare");
32   }
33 
operator ==(const Selector & rhs) const34   bool ComplexSelector::operator== (const Selector& rhs) const
35   {
36     if (auto sel = Cast<SelectorList>(&rhs)) { return *this == *sel; }
37     if (auto sel = Cast<ComplexSelector>(&rhs)) { return *sel == *this; }
38     if (auto sel = Cast<CompoundSelector>(&rhs)) { return *this == *sel; }
39     if (auto sel = Cast<SimpleSelector>(&rhs)) { return *this == *sel; }
40     throw std::runtime_error("invalid selector base classes to compare");
41   }
42 
operator ==(const Selector & rhs) const43   bool SelectorCombinator::operator== (const Selector& rhs) const
44   {
45     if (auto cpx = Cast<SelectorCombinator>(&rhs)) { return *this == *cpx; }
46     return false;
47   }
48 
operator ==(const Selector & rhs) const49   bool CompoundSelector::operator== (const Selector& rhs) const
50   {
51     if (auto sel = Cast<SimpleSelector>(&rhs)) { return *this == *sel; }
52     if (auto sel = Cast<SelectorList>(&rhs)) { return *this == *sel; }
53     if (auto sel = Cast<ComplexSelector>(&rhs)) { return *this == *sel; }
54     if (auto sel = Cast<CompoundSelector>(&rhs)) { return *this == *sel; }
55     throw std::runtime_error("invalid selector base classes to compare");
56   }
57 
operator ==(const Selector & rhs) const58   bool SimpleSelector::operator== (const Selector& rhs) const
59   {
60     if (auto sel = Cast<SelectorList>(&rhs)) { return *this == *sel; }
61     if (auto sel = Cast<ComplexSelector>(&rhs)) { return *this == *sel; }
62     if (auto sel = Cast<CompoundSelector>(&rhs)) { return *this == *sel; }
63     if (auto sel = Cast<SimpleSelector>(&rhs)) return *this == *sel;
64     throw std::runtime_error("invalid selector base classes to compare");
65   }
66 
67   /*#########################################################################*/
68   /*#########################################################################*/
69 
operator ==(const SelectorList & rhs) const70   bool SelectorList::operator== (const SelectorList& rhs) const
71   {
72     if (&rhs == this) return true;
73     if (rhs.length() != length()) return false;
74     std::unordered_set<const ComplexSelector*, PtrObjHash, PtrObjEquality> lhs_set;
75     lhs_set.reserve(length());
76     for (const ComplexSelectorObj& element : elements()) {
77       lhs_set.insert(element.ptr());
78     }
79     for (const ComplexSelectorObj& element : rhs.elements()) {
80       if (lhs_set.find(element.ptr()) == lhs_set.end()) return false;
81     }
82     return true;
83   }
84 
85 
86 
87   /*#########################################################################*/
88   // Compare SelectorList against all other selector types
89   /*#########################################################################*/
90 
operator ==(const ComplexSelector & rhs) const91   bool SelectorList::operator== (const ComplexSelector& rhs) const
92   {
93     // If both are empty they are equal
94     if (empty() && rhs.empty()) return true;
95     // Must have exactly one item
96     if (length() != 1) return false;
97     // Compare simple selectors
98     return *get(0) == rhs;
99   }
100 
operator ==(const CompoundSelector & rhs) const101   bool SelectorList::operator== (const CompoundSelector& rhs) const
102   {
103     // If both are empty they are equal
104     if (empty() && rhs.empty()) return true;
105     // Must have exactly one item
106     if (length() != 1) return false;
107     // Compare simple selectors
108     return *get(0) == rhs;
109   }
110 
operator ==(const SimpleSelector & rhs) const111   bool SelectorList::operator== (const SimpleSelector& rhs) const
112   {
113     // If both are empty they are equal
114     if (empty() && rhs.empty()) return true;
115     // Must have exactly one item
116     if (length() != 1) return false;
117     // Compare simple selectors
118     return *get(0) == rhs;
119   }
120 
121   /*#########################################################################*/
122   // Compare ComplexSelector against itself
123   /*#########################################################################*/
124 
operator ==(const ComplexSelector & rhs) const125   bool ComplexSelector::operator== (const ComplexSelector& rhs) const
126   {
127     size_t len = length();
128     size_t rlen = rhs.length();
129     if (len != rlen) return false;
130     for (size_t i = 0; i < len; i += 1) {
131       if (*get(i) != *rhs.get(i)) return false;
132     }
133     return true;
134   }
135 
136   /*#########################################################################*/
137   // Compare ComplexSelector against all other selector types
138   /*#########################################################################*/
139 
operator ==(const SelectorList & rhs) const140   bool ComplexSelector::operator== (const SelectorList& rhs) const
141   {
142     // If both are empty they are equal
143     if (empty() && rhs.empty()) return true;
144     // Must have exactly one item
145     if (rhs.length() != 1) return false;
146     // Compare complex selector
147     return *this == *rhs.get(0);
148   }
149 
operator ==(const CompoundSelector & rhs) const150   bool ComplexSelector::operator== (const CompoundSelector& rhs) const
151   {
152     // If both are empty they are equal
153     if (empty() && rhs.empty()) return true;
154     // Must have exactly one item
155     if (length() != 1) return false;
156     // Compare compound selector
157     return *get(0) == rhs;
158   }
159 
operator ==(const SimpleSelector & rhs) const160   bool ComplexSelector::operator== (const SimpleSelector& rhs) const
161   {
162     // If both are empty they are equal
163     if (empty() && rhs.empty()) return true;
164     // Must have exactly one item
165     if (length() != 1) return false;
166     // Compare simple selectors
167     return *get(0) == rhs;
168   }
169 
170   /*#########################################################################*/
171   // Compare SelectorCombinator against itself
172   /*#########################################################################*/
173 
operator ==(const SelectorCombinator & rhs) const174   bool SelectorCombinator::operator==(const SelectorCombinator& rhs) const
175   {
176     return combinator() == rhs.combinator();
177   }
178 
179   /*#########################################################################*/
180   // Compare SelectorCombinator against SelectorComponent
181   /*#########################################################################*/
182 
operator ==(const SelectorComponent & rhs) const183   bool SelectorCombinator::operator==(const SelectorComponent& rhs) const
184   {
185     if (const SelectorCombinator * sel = rhs.getCombinator()) {
186       return *this == *sel;
187     }
188     return false;
189   }
190 
operator ==(const SelectorComponent & rhs) const191   bool CompoundSelector::operator==(const SelectorComponent& rhs) const
192   {
193     if (const CompoundSelector * sel = rhs.getCompound()) {
194       return *this == *sel;
195     }
196     return false;
197   }
198 
199   /*#########################################################################*/
200   // Compare CompoundSelector against itself
201   /*#########################################################################*/
202   // ToDo: Verifiy implementation
203   /*#########################################################################*/
204 
operator ==(const CompoundSelector & rhs) const205   bool CompoundSelector::operator== (const CompoundSelector& rhs) const
206   {
207     // std::cerr << "comp vs comp\n";
208     if (&rhs == this) return true;
209     if (rhs.length() != length()) return false;
210     std::unordered_set<const SimpleSelector*, PtrObjHash, PtrObjEquality> lhs_set;
211     lhs_set.reserve(length());
212     for (const SimpleSelectorObj& element : elements()) {
213       lhs_set.insert(element.ptr());
214     }
215     // there is no break?!
216     for (const SimpleSelectorObj& element : rhs.elements()) {
217       if (lhs_set.find(element.ptr()) == lhs_set.end()) return false;
218     }
219     return true;
220   }
221 
222 
223   /*#########################################################################*/
224   // Compare CompoundSelector against all other selector types
225   /*#########################################################################*/
226 
operator ==(const SelectorList & rhs) const227   bool CompoundSelector::operator== (const SelectorList& rhs) const
228   {
229     // If both are empty they are equal
230     if (empty() && rhs.empty()) return true;
231     // Must have exactly one item
232     if (rhs.length() != 1) return false;
233     // Compare complex selector
234     return *this == *rhs.get(0);
235   }
236 
operator ==(const ComplexSelector & rhs) const237   bool CompoundSelector::operator== (const ComplexSelector& rhs) const
238   {
239     // If both are empty they are equal
240     if (empty() && rhs.empty()) return true;
241     // Must have exactly one item
242     if (rhs.length() != 1) return false;
243     // Compare compound selector
244     return *this == *rhs.get(0);
245   }
246 
operator ==(const SimpleSelector & rhs) const247   bool CompoundSelector::operator== (const SimpleSelector& rhs) const
248   {
249     // If both are empty they are equal
250     if (empty() && rhs.empty()) return false;
251     // Must have exactly one item
252     size_t rlen = length();
253     if (rlen > 1) return false;
254     if (rlen == 0) return true;
255     // Compare simple selectors
256     return *get(0) < rhs;
257   }
258 
259   /*#########################################################################*/
260   // Compare SimpleSelector against itself (upcast from abstract base)
261   /*#########################################################################*/
262 
263   // DOES NOT EXIST FOR ABSTRACT BASE CLASS
264 
265   /*#########################################################################*/
266   // Compare SimpleSelector against all other selector types
267   /*#########################################################################*/
268 
operator ==(const SelectorList & rhs) const269   bool SimpleSelector::operator== (const SelectorList& rhs) const
270   {
271     // If both are empty they are equal
272     if (empty() && rhs.empty()) return true;
273     // Must have exactly one item
274     if (rhs.length() != 1) return false;
275     // Compare complex selector
276     return *this == *rhs.get(0);
277   }
278 
operator ==(const ComplexSelector & rhs) const279   bool SimpleSelector::operator== (const ComplexSelector& rhs) const
280   {
281     // If both are empty they are equal
282     if (empty() && rhs.empty()) return true;
283     // Must have exactly one item
284     if (rhs.length() != 1) return false;
285     // Compare compound selector
286     return *this == *rhs.get(0);
287   }
288 
operator ==(const CompoundSelector & rhs) const289   bool SimpleSelector::operator== (const CompoundSelector& rhs) const
290   {
291     // If both are empty they are equal
292     if (empty() && rhs.empty()) return false;
293     // Must have exactly one item
294     if (rhs.length() != 1) return false;
295     // Compare simple selector
296     return *this == *rhs.get(0);
297   }
298 
299   /*#########################################################################*/
300   /*#########################################################################*/
301 
operator ==(const SimpleSelector & rhs) const302   bool IDSelector::operator== (const SimpleSelector& rhs) const
303   {
304     auto sel = Cast<IDSelector>(&rhs);
305     return sel ? *this == *sel : false;
306   }
307 
operator ==(const SimpleSelector & rhs) const308   bool TypeSelector::operator== (const SimpleSelector& rhs) const
309   {
310     auto sel = Cast<TypeSelector>(&rhs);
311     return sel ? *this == *sel : false;
312   }
313 
operator ==(const SimpleSelector & rhs) const314   bool ClassSelector::operator== (const SimpleSelector& rhs) const
315   {
316     auto sel = Cast<ClassSelector>(&rhs);
317     return sel ? *this == *sel : false;
318   }
319 
operator ==(const SimpleSelector & rhs) const320   bool PseudoSelector::operator== (const SimpleSelector& rhs) const
321   {
322     auto sel = Cast<PseudoSelector>(&rhs);
323     return sel ? *this == *sel : false;
324   }
325 
operator ==(const SimpleSelector & rhs) const326   bool AttributeSelector::operator== (const SimpleSelector& rhs) const
327   {
328     auto sel = Cast<AttributeSelector>(&rhs);
329     return sel ? *this == *sel : false;
330   }
331 
operator ==(const SimpleSelector & rhs) const332   bool PlaceholderSelector::operator== (const SimpleSelector& rhs) const
333   {
334     auto sel = Cast<PlaceholderSelector>(&rhs);
335     return sel ? *this == *sel : false;
336   }
337 
338   /*#########################################################################*/
339   /*#########################################################################*/
340 
operator ==(const IDSelector & rhs) const341   bool IDSelector::operator== (const IDSelector& rhs) const
342   {
343     // ID has no namespacing
344     return name() == rhs.name();
345   }
346 
operator ==(const TypeSelector & rhs) const347   bool TypeSelector::operator== (const TypeSelector& rhs) const
348   {
349     return is_ns_eq(rhs) && name() == rhs.name();
350   }
351 
operator ==(const ClassSelector & rhs) const352   bool ClassSelector::operator== (const ClassSelector& rhs) const
353   {
354     // Class has no namespacing
355     return name() == rhs.name();
356   }
357 
operator ==(const PlaceholderSelector & rhs) const358   bool PlaceholderSelector::operator== (const PlaceholderSelector& rhs) const
359   {
360     // Placeholder has no namespacing
361     return name() == rhs.name();
362   }
363 
operator ==(const AttributeSelector & rhs) const364   bool AttributeSelector::operator== (const AttributeSelector& rhs) const
365   {
366     // smaller return, equal go on, bigger abort
367     if (is_ns_eq(rhs)) {
368       if (name() != rhs.name()) return false;
369       if (matcher() != rhs.matcher()) return false;
370       if (modifier() != rhs.modifier()) return false;
371       const String* lhs_val = value();
372       const String* rhs_val = rhs.value();
373       return PtrObjEquality()(lhs_val, rhs_val);
374     }
375     else { return false; }
376   }
377 
operator ==(const PseudoSelector & rhs) const378   bool PseudoSelector::operator== (const PseudoSelector& rhs) const
379   {
380     if (is_ns_eq(rhs)) {
381       if (name() != rhs.name()) return false;
382       if (isElement() != rhs.isElement()) return false;
383       const String* lhs_arg = argument();
384       const String* rhs_arg = rhs.argument();
385       if (!PtrObjEquality()(lhs_arg, rhs_arg)) return false;
386       const SelectorList* lhs_sel = selector();
387       const SelectorList* rhs_sel = rhs.selector();
388       return PtrObjEquality()(lhs_sel, rhs_sel);
389     }
390     else { return false; }
391   }
392 
393   /*#########################################################################*/
394   /*#########################################################################*/
395 
396 }
397