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 |
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 |