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
7namespace 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
15 bool SelectorList::operator== (const Expression& rhs) const
16 {
17 if (auto l = Cast<List>(ptr: &rhs)) { return *this == *l; }
18 if (auto s = Cast<Selector>(ptr: &rhs)) { return *this == *s; }
19 if (Cast<String>(ptr: &rhs) || Cast<Null>(ptr: &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
24 bool SelectorList::operator== (const Selector& rhs) const
25 {
26 if (auto sel = Cast<SelectorList>(ptr: &rhs)) { return *this == *sel; }
27 if (auto sel = Cast<ComplexSelector>(ptr: &rhs)) { return *this == *sel; }
28 if (auto sel = Cast<CompoundSelector>(ptr: &rhs)) { return *this == *sel; }
29 if (auto sel = Cast<SimpleSelector>(ptr: &rhs)) { return *this == *sel; }
30 if (auto list = Cast<List>(ptr: &rhs)) { return *this == *list; }
31 throw std::runtime_error("invalid selector base classes to compare");
32 }
33
34 bool ComplexSelector::operator== (const Selector& rhs) const
35 {
36 if (auto sel = Cast<SelectorList>(ptr: &rhs)) { return *this == *sel; }
37 if (auto sel = Cast<ComplexSelector>(ptr: &rhs)) { return *sel == *this; }
38 if (auto sel = Cast<CompoundSelector>(ptr: &rhs)) { return *this == *sel; }
39 if (auto sel = Cast<SimpleSelector>(ptr: &rhs)) { return *this == *sel; }
40 throw std::runtime_error("invalid selector base classes to compare");
41 }
42
43 bool SelectorCombinator::operator== (const Selector& rhs) const
44 {
45 if (auto cpx = Cast<SelectorCombinator>(ptr: &rhs)) { return *this == *cpx; }
46 return false;
47 }
48
49 bool CompoundSelector::operator== (const Selector& rhs) const
50 {
51 if (auto sel = Cast<SimpleSelector>(ptr: &rhs)) { return *this == *sel; }
52 if (auto sel = Cast<SelectorList>(ptr: &rhs)) { return *this == *sel; }
53 if (auto sel = Cast<ComplexSelector>(ptr: &rhs)) { return *this == *sel; }
54 if (auto sel = Cast<CompoundSelector>(ptr: &rhs)) { return *this == *sel; }
55 throw std::runtime_error("invalid selector base classes to compare");
56 }
57
58 bool SimpleSelector::operator== (const Selector& rhs) const
59 {
60 if (auto sel = Cast<SelectorList>(ptr: &rhs)) { return *this == *sel; }
61 if (auto sel = Cast<ComplexSelector>(ptr: &rhs)) { return *this == *sel; }
62 if (auto sel = Cast<CompoundSelector>(ptr: &rhs)) { return *this == *sel; }
63 if (auto sel = Cast<SimpleSelector>(ptr: &rhs)) return *this == *sel;
64 throw std::runtime_error("invalid selector base classes to compare");
65 }
66
67 /*#########################################################################*/
68 /*#########################################################################*/
69
70 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(n: length());
76 for (const ComplexSelectorObj& element : elements()) {
77 lhs_set.insert(x: element.ptr());
78 }
79 for (const ComplexSelectorObj& element : rhs.elements()) {
80 if (lhs_set.find(x: 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
91 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(i: 0) == rhs;
99 }
100
101 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(i: 0) == rhs;
109 }
110
111 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(i: 0) == rhs;
119 }
120
121 /*#########################################################################*/
122 // Compare ComplexSelector against itself
123 /*#########################################################################*/
124
125 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
140 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(i: 0);
148 }
149
150 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(i: 0) == rhs;
158 }
159
160 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(i: 0) == rhs;
168 }
169
170 /*#########################################################################*/
171 // Compare SelectorCombinator against itself
172 /*#########################################################################*/
173
174 bool SelectorCombinator::operator==(const SelectorCombinator& rhs) const
175 {
176 return combinator() == rhs.combinator();
177 }
178
179 /*#########################################################################*/
180 // Compare SelectorCombinator against SelectorComponent
181 /*#########################################################################*/
182
183 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
191 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
205 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(n: length());
212 for (const SimpleSelectorObj& element : elements()) {
213 lhs_set.insert(x: element.ptr());
214 }
215 // there is no break?!
216 for (const SimpleSelectorObj& element : rhs.elements()) {
217 if (lhs_set.find(x: 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
227 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(i: 0);
235 }
236
237 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(i: 0);
245 }
246
247 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(i: 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
269 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(i: 0);
277 }
278
279 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(i: 0);
287 }
288
289 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(i: 0);
297 }
298
299 /*#########################################################################*/
300 /*#########################################################################*/
301
302 bool IDSelector::operator== (const SimpleSelector& rhs) const
303 {
304 auto sel = Cast<IDSelector>(ptr: &rhs);
305 return sel ? *this == *sel : false;
306 }
307
308 bool TypeSelector::operator== (const SimpleSelector& rhs) const
309 {
310 auto sel = Cast<TypeSelector>(ptr: &rhs);
311 return sel ? *this == *sel : false;
312 }
313
314 bool ClassSelector::operator== (const SimpleSelector& rhs) const
315 {
316 auto sel = Cast<ClassSelector>(ptr: &rhs);
317 return sel ? *this == *sel : false;
318 }
319
320 bool PseudoSelector::operator== (const SimpleSelector& rhs) const
321 {
322 auto sel = Cast<PseudoSelector>(ptr: &rhs);
323 return sel ? *this == *sel : false;
324 }
325
326 bool AttributeSelector::operator== (const SimpleSelector& rhs) const
327 {
328 auto sel = Cast<AttributeSelector>(ptr: &rhs);
329 return sel ? *this == *sel : false;
330 }
331
332 bool PlaceholderSelector::operator== (const SimpleSelector& rhs) const
333 {
334 auto sel = Cast<PlaceholderSelector>(ptr: &rhs);
335 return sel ? *this == *sel : false;
336 }
337
338 /*#########################################################################*/
339 /*#########################################################################*/
340
341 bool IDSelector::operator== (const IDSelector& rhs) const
342 {
343 // ID has no namespacing
344 return name() == rhs.name();
345 }
346
347 bool TypeSelector::operator== (const TypeSelector& rhs) const
348 {
349 return is_ns_eq(r: rhs) && name() == rhs.name();
350 }
351
352 bool ClassSelector::operator== (const ClassSelector& rhs) const
353 {
354 // Class has no namespacing
355 return name() == rhs.name();
356 }
357
358 bool PlaceholderSelector::operator== (const PlaceholderSelector& rhs) const
359 {
360 // Placeholder has no namespacing
361 return name() == rhs.name();
362 }
363
364 bool AttributeSelector::operator== (const AttributeSelector& rhs) const
365 {
366 // smaller return, equal go on, bigger abort
367 if (is_ns_eq(r: 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
378 bool PseudoSelector::operator== (const PseudoSelector& rhs) const
379 {
380 if (is_ns_eq(r: 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

source code of gtk/subprojects/libsass/src/ast_sel_cmp.cpp