// sass.hpp must go before all system headers to get the // __EXTENSIONS__ fix on Solaris. #include "sass.hpp" #include "ast_selectors.hpp" namespace Sass { /*#########################################################################*/ // Compare against base class on right hand side // try to find the most specialized implementation /*#########################################################################*/ // Selector lists can be compared to comma lists bool SelectorList::operator== (const Expression& rhs) const { if (auto l = Cast(&rhs)) { return *this == *l; } if (auto s = Cast(&rhs)) { return *this == *s; } if (Cast(&rhs) || Cast(&rhs)) { return false; } throw std::runtime_error("invalid selector base classes to compare"); } // Selector lists can be compared to comma lists bool SelectorList::operator== (const Selector& rhs) const { if (auto sel = Cast(&rhs)) { return *this == *sel; } if (auto sel = Cast(&rhs)) { return *this == *sel; } if (auto sel = Cast(&rhs)) { return *this == *sel; } if (auto sel = Cast(&rhs)) { return *this == *sel; } if (auto list = Cast(&rhs)) { return *this == *list; } throw std::runtime_error("invalid selector base classes to compare"); } bool ComplexSelector::operator== (const Selector& rhs) const { if (auto sel = Cast(&rhs)) { return *this == *sel; } if (auto sel = Cast(&rhs)) { return *sel == *this; } if (auto sel = Cast(&rhs)) { return *this == *sel; } if (auto sel = Cast(&rhs)) { return *this == *sel; } throw std::runtime_error("invalid selector base classes to compare"); } bool SelectorCombinator::operator== (const Selector& rhs) const { if (auto cpx = Cast(&rhs)) { return *this == *cpx; } return false; } bool CompoundSelector::operator== (const Selector& rhs) const { if (auto sel = Cast(&rhs)) { return *this == *sel; } if (auto sel = Cast(&rhs)) { return *this == *sel; } if (auto sel = Cast(&rhs)) { return *this == *sel; } if (auto sel = Cast(&rhs)) { return *this == *sel; } throw std::runtime_error("invalid selector base classes to compare"); } bool SimpleSelector::operator== (const Selector& rhs) const { if (auto sel = Cast(&rhs)) { return *this == *sel; } if (auto sel = Cast(&rhs)) { return *this == *sel; } if (auto sel = Cast(&rhs)) { return *this == *sel; } if (auto sel = Cast(&rhs)) return *this == *sel; throw std::runtime_error("invalid selector base classes to compare"); } /*#########################################################################*/ /*#########################################################################*/ bool SelectorList::operator== (const SelectorList& rhs) const { if (&rhs == this) return true; if (rhs.length() != length()) return false; std::unordered_set lhs_set; lhs_set.reserve(length()); for (const ComplexSelectorObj& element : elements()) { lhs_set.insert(element.ptr()); } for (const ComplexSelectorObj& element : rhs.elements()) { if (lhs_set.find(element.ptr()) == lhs_set.end()) return false; } return true; } /*#########################################################################*/ // Compare SelectorList against all other selector types /*#########################################################################*/ bool SelectorList::operator== (const ComplexSelector& rhs) const { // If both are empty they are equal if (empty() && rhs.empty()) return true; // Must have exactly one item if (length() != 1) return false; // Compare simple selectors return *get(0) == rhs; } bool SelectorList::operator== (const CompoundSelector& rhs) const { // If both are empty they are equal if (empty() && rhs.empty()) return true; // Must have exactly one item if (length() != 1) return false; // Compare simple selectors return *get(0) == rhs; } bool SelectorList::operator== (const SimpleSelector& rhs) const { // If both are empty they are equal if (empty() && rhs.empty()) return true; // Must have exactly one item if (length() != 1) return false; // Compare simple selectors return *get(0) == rhs; } /*#########################################################################*/ // Compare ComplexSelector against itself /*#########################################################################*/ bool ComplexSelector::operator== (const ComplexSelector& rhs) const { size_t len = length(); size_t rlen = rhs.length(); if (len != rlen) return false; for (size_t i = 0; i < len; i += 1) { if (*get(i) != *rhs.get(i)) return false; } return true; } /*#########################################################################*/ // Compare ComplexSelector against all other selector types /*#########################################################################*/ bool ComplexSelector::operator== (const SelectorList& rhs) const { // If both are empty they are equal if (empty() && rhs.empty()) return true; // Must have exactly one item if (rhs.length() != 1) return false; // Compare complex selector return *this == *rhs.get(0); } bool ComplexSelector::operator== (const CompoundSelector& rhs) const { // If both are empty they are equal if (empty() && rhs.empty()) return true; // Must have exactly one item if (length() != 1) return false; // Compare compound selector return *get(0) == rhs; } bool ComplexSelector::operator== (const SimpleSelector& rhs) const { // If both are empty they are equal if (empty() && rhs.empty()) return true; // Must have exactly one item if (length() != 1) return false; // Compare simple selectors return *get(0) == rhs; } /*#########################################################################*/ // Compare SelectorCombinator against itself /*#########################################################################*/ bool SelectorCombinator::operator==(const SelectorCombinator& rhs) const { return combinator() == rhs.combinator(); } /*#########################################################################*/ // Compare SelectorCombinator against SelectorComponent /*#########################################################################*/ bool SelectorCombinator::operator==(const SelectorComponent& rhs) const { if (const SelectorCombinator * sel = rhs.getCombinator()) { return *this == *sel; } return false; } bool CompoundSelector::operator==(const SelectorComponent& rhs) const { if (const CompoundSelector * sel = rhs.getCompound()) { return *this == *sel; } return false; } /*#########################################################################*/ // Compare CompoundSelector against itself /*#########################################################################*/ // ToDo: Verifiy implementation /*#########################################################################*/ bool CompoundSelector::operator== (const CompoundSelector& rhs) const { // std::cerr << "comp vs comp\n"; if (&rhs == this) return true; if (rhs.length() != length()) return false; std::unordered_set lhs_set; lhs_set.reserve(length()); for (const SimpleSelectorObj& element : elements()) { lhs_set.insert(element.ptr()); } // there is no break?! for (const SimpleSelectorObj& element : rhs.elements()) { if (lhs_set.find(element.ptr()) == lhs_set.end()) return false; } return true; } /*#########################################################################*/ // Compare CompoundSelector against all other selector types /*#########################################################################*/ bool CompoundSelector::operator== (const SelectorList& rhs) const { // If both are empty they are equal if (empty() && rhs.empty()) return true; // Must have exactly one item if (rhs.length() != 1) return false; // Compare complex selector return *this == *rhs.get(0); } bool CompoundSelector::operator== (const ComplexSelector& rhs) const { // If both are empty they are equal if (empty() && rhs.empty()) return true; // Must have exactly one item if (rhs.length() != 1) return false; // Compare compound selector return *this == *rhs.get(0); } bool CompoundSelector::operator== (const SimpleSelector& rhs) const { // If both are empty they are equal if (empty() && rhs.empty()) return false; // Must have exactly one item size_t rlen = length(); if (rlen > 1) return false; if (rlen == 0) return true; // Compare simple selectors return *get(0) < rhs; } /*#########################################################################*/ // Compare SimpleSelector against itself (upcast from abstract base) /*#########################################################################*/ // DOES NOT EXIST FOR ABSTRACT BASE CLASS /*#########################################################################*/ // Compare SimpleSelector against all other selector types /*#########################################################################*/ bool SimpleSelector::operator== (const SelectorList& rhs) const { // If both are empty they are equal if (empty() && rhs.empty()) return true; // Must have exactly one item if (rhs.length() != 1) return false; // Compare complex selector return *this == *rhs.get(0); } bool SimpleSelector::operator== (const ComplexSelector& rhs) const { // If both are empty they are equal if (empty() && rhs.empty()) return true; // Must have exactly one item if (rhs.length() != 1) return false; // Compare compound selector return *this == *rhs.get(0); } bool SimpleSelector::operator== (const CompoundSelector& rhs) const { // If both are empty they are equal if (empty() && rhs.empty()) return false; // Must have exactly one item if (rhs.length() != 1) return false; // Compare simple selector return *this == *rhs.get(0); } /*#########################################################################*/ /*#########################################################################*/ bool IDSelector::operator== (const SimpleSelector& rhs) const { auto sel = Cast(&rhs); return sel ? *this == *sel : false; } bool TypeSelector::operator== (const SimpleSelector& rhs) const { auto sel = Cast(&rhs); return sel ? *this == *sel : false; } bool ClassSelector::operator== (const SimpleSelector& rhs) const { auto sel = Cast(&rhs); return sel ? *this == *sel : false; } bool PseudoSelector::operator== (const SimpleSelector& rhs) const { auto sel = Cast(&rhs); return sel ? *this == *sel : false; } bool AttributeSelector::operator== (const SimpleSelector& rhs) const { auto sel = Cast(&rhs); return sel ? *this == *sel : false; } bool PlaceholderSelector::operator== (const SimpleSelector& rhs) const { auto sel = Cast(&rhs); return sel ? *this == *sel : false; } /*#########################################################################*/ /*#########################################################################*/ bool IDSelector::operator== (const IDSelector& rhs) const { // ID has no namespacing return name() == rhs.name(); } bool TypeSelector::operator== (const TypeSelector& rhs) const { return is_ns_eq(rhs) && name() == rhs.name(); } bool ClassSelector::operator== (const ClassSelector& rhs) const { // Class has no namespacing return name() == rhs.name(); } bool PlaceholderSelector::operator== (const PlaceholderSelector& rhs) const { // Placeholder has no namespacing return name() == rhs.name(); } bool AttributeSelector::operator== (const AttributeSelector& rhs) const { // smaller return, equal go on, bigger abort if (is_ns_eq(rhs)) { if (name() != rhs.name()) return false; if (matcher() != rhs.matcher()) return false; if (modifier() != rhs.modifier()) return false; const String* lhs_val = value(); const String* rhs_val = rhs.value(); return PtrObjEquality()(lhs_val, rhs_val); } else { return false; } } bool PseudoSelector::operator== (const PseudoSelector& rhs) const { if (is_ns_eq(rhs)) { if (name() != rhs.name()) return false; if (isElement() != rhs.isElement()) return false; const String* lhs_arg = argument(); const String* rhs_arg = rhs.argument(); if (!PtrObjEquality()(lhs_arg, rhs_arg)) return false; const SelectorList* lhs_sel = selector(); const SelectorList* rhs_sel = rhs.selector(); return PtrObjEquality()(lhs_sel, rhs_sel); } else { return false; } } /*#########################################################################*/ /*#########################################################################*/ }