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