From 122d9f37a7ad3766af114f8cefb1471b82444414 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Wed, 21 Nov 2018 02:00:22 +0000 Subject: [PATCH] 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). --- src/ast.cpp | 37 ++++++++++--------------------------- src/ast.hpp | 2 +- src/ast_fwd_decl.hpp | 13 +++++++++++++ 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/ast.cpp b/src/ast.cpp index e5fab50af..74bf0e176 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -459,34 +459,17 @@ namespace Sass { bool Selector_List::operator== (const Selector_List& rhs) const { - // for array access - size_t i = 0, n = 0; - size_t iL = length(); - size_t nL = rhs.length(); - // create temporary vectors and sort them - std::vector l_lst = this->elements(); - std::vector r_lst = rhs.elements(); - std::sort(l_lst.begin(), l_lst.end(), OrderNodes()); - std::sort(r_lst.begin(), r_lst.end(), OrderNodes()); - // process loop - while (true) - { - // first check for valid index - if (i == iL) return iL == nL; - else if (n == nL) return iL == nL; - // the access the vector items - Complex_Selector_Obj l = l_lst[i]; - Complex_Selector_Obj r = r_lst[n]; - // skip nulls - if (!l) ++i; - else if (!r) ++n; - // do the check - else if (*l != *r) - { return false; } - // advance - ++i; ++n; + if (&rhs == this) return true; + if (rhs.length() != length()) return false; + std::unordered_set lhs_set; + lhs_set.reserve(length()); + for (const Complex_Selector_Obj &element : elements()) { + lhs_set.insert(element.ptr()); } - // there is no break?! + for (const Complex_Selector_Obj &element : rhs.elements()) { + if (lhs_set.find(element.ptr()) == lhs_set.end()) return false; + } + return true; } bool Selector_List::operator< (const Selector& rhs) const diff --git a/src/ast.hpp b/src/ast.hpp index 3f6efa3f0..7e3747772 100644 --- a/src/ast.hpp +++ b/src/ast.hpp @@ -2288,7 +2288,7 @@ namespace Sass { name += ns_ + "|"; return name + name_; } - size_t hash() const override + virtual size_t hash() const override { if (hash_ == 0) { hash_combine(hash_, std::hash()(SELECTOR)); diff --git a/src/ast_fwd_decl.hpp b/src/ast_fwd_decl.hpp index 49c1e7809..e43cfbe9e 100644 --- a/src/ast_fwd_decl.hpp +++ b/src/ast_fwd_decl.hpp @@ -383,6 +383,19 @@ namespace Sass { } }; + struct HashPtr { + template + size_t operator() (const T *ref) const { + return ref->hash(); + } + }; + struct ComparePtrs { + template + bool operator() (const T *lhs, const T *rhs) const { + return *lhs == *rhs; + } + }; + // ########################################################################### // some often used typedefs // ###########################################################################