Skip to content

Commit 122d9f3

Browse files
glebmxzyfer
authored andcommitted
Clean up Selector_List::operator==
Implements equality for selector lists in a cleaner and more efficient manner. Related issue: #2666 (likely fixed by this change but I haven't verified).
1 parent 754b338 commit 122d9f3

File tree

3 files changed

+24
-28
lines changed

3 files changed

+24
-28
lines changed

src/ast.cpp

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -459,34 +459,17 @@ namespace Sass {
459459

460460
bool Selector_List::operator== (const Selector_List& rhs) const
461461
{
462-
// for array access
463-
size_t i = 0, n = 0;
464-
size_t iL = length();
465-
size_t nL = rhs.length();
466-
// create temporary vectors and sort them
467-
std::vector<Complex_Selector_Obj> l_lst = this->elements();
468-
std::vector<Complex_Selector_Obj> r_lst = rhs.elements();
469-
std::sort(l_lst.begin(), l_lst.end(), OrderNodes());
470-
std::sort(r_lst.begin(), r_lst.end(), OrderNodes());
471-
// process loop
472-
while (true)
473-
{
474-
// first check for valid index
475-
if (i == iL) return iL == nL;
476-
else if (n == nL) return iL == nL;
477-
// the access the vector items
478-
Complex_Selector_Obj l = l_lst[i];
479-
Complex_Selector_Obj r = r_lst[n];
480-
// skip nulls
481-
if (!l) ++i;
482-
else if (!r) ++n;
483-
// do the check
484-
else if (*l != *r)
485-
{ return false; }
486-
// advance
487-
++i; ++n;
462+
if (&rhs == this) return true;
463+
if (rhs.length() != length()) return false;
464+
std::unordered_set<const Complex_Selector *, HashPtr, ComparePtrs> lhs_set;
465+
lhs_set.reserve(length());
466+
for (const Complex_Selector_Obj &element : elements()) {
467+
lhs_set.insert(element.ptr());
488468
}
489-
// there is no break?!
469+
for (const Complex_Selector_Obj &element : rhs.elements()) {
470+
if (lhs_set.find(element.ptr()) == lhs_set.end()) return false;
471+
}
472+
return true;
490473
}
491474

492475
bool Selector_List::operator< (const Selector& rhs) const

src/ast.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2288,7 +2288,7 @@ namespace Sass {
22882288
name += ns_ + "|";
22892289
return name + name_;
22902290
}
2291-
size_t hash() const override
2291+
virtual size_t hash() const override
22922292
{
22932293
if (hash_ == 0) {
22942294
hash_combine(hash_, std::hash<int>()(SELECTOR));

src/ast_fwd_decl.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,19 @@ namespace Sass {
383383
}
384384
};
385385

386+
struct HashPtr {
387+
template <class T>
388+
size_t operator() (const T *ref) const {
389+
return ref->hash();
390+
}
391+
};
392+
struct ComparePtrs {
393+
template <class T>
394+
bool operator() (const T *lhs, const T *rhs) const {
395+
return *lhs == *rhs;
396+
}
397+
};
398+
386399
// ###########################################################################
387400
// some often used typedefs
388401
// ###########################################################################

0 commit comments

Comments
 (0)