@@ -30,6 +30,23 @@ namespace Sass {
30
30
SASS_MEMORY_CAST (Supports_Operator, cond);
31
31
}
32
32
33
+ size_t HashExpression::operator () (Expression_Obj ex) const {
34
+ return ex ? ex->hash () : 0 ;
35
+ }
36
+
37
+ size_t HashSimpleSelector::operator () (Simple_Selector_Obj ex) const {
38
+ return ex ? ex->hash () : 0 ;
39
+ }
40
+
41
+
42
+ bool CompareExpression::operator ()(const Expression_Obj& lhs, const Expression_Obj& rhs) const {
43
+ return lhs && rhs && lhs->eq (*rhs);
44
+ }
45
+
46
+ bool CompareSimpleSelector::operator ()(Simple_Selector_Obj lhs, Simple_Selector_Obj rhs) const {
47
+ return &lhs && &rhs && *lhs == *rhs;
48
+ }
49
+
33
50
std::string & str_ltrim (std::string & str)
34
51
{
35
52
auto it2 = std::find_if ( str.begin () , str.end () , [](char ch){ return !std::isspace<char >(ch , std::locale::classic () ) ; } );
@@ -286,11 +303,11 @@ namespace Sass {
286
303
l_h = l ? &l->head () : 0 ;
287
304
r_h = r ? &r->head () : 0 ;
288
305
}
289
- // fail if only one is null
290
- else if (!r_h) return !l_h;
291
- else if (!l_h) return ! r_h;
292
- // heads ok and equal
293
- else if (*l_h == *r_h)
306
+ // equals if other head is empty
307
+ else if ((!l_h && !r_h) ||
308
+ (!l_h && r_h-> empty ()) ||
309
+ (!r_h && l_h-> empty ()) ||
310
+ (*l_h == *r_h) )
294
311
{
295
312
// check combinator after heads
296
313
if (l->combinator () != r->combinator ())
@@ -321,24 +338,68 @@ namespace Sass {
321
338
return unified.detach ();
322
339
}
323
340
341
+ bool Selector::operator == (const Selector& rhs) const
342
+ {
343
+ if (Selector_List_Ptr_Const sl = dynamic_cast <Selector_List_Ptr_Const>(this )) return *sl == rhs;
344
+ if (Simple_Selector_Ptr_Const sp = dynamic_cast <Simple_Selector_Ptr_Const>(this )) return *sp == rhs;
345
+ throw " invalid selector base classes to compare" ;
346
+ return false ;
347
+ }
348
+
349
+ bool Selector::operator < (const Selector& rhs) const
350
+ {
351
+ if (Selector_List_Ptr_Const sl = dynamic_cast <Selector_List_Ptr_Const>(this )) return *sl < rhs;
352
+ if (Simple_Selector_Ptr_Const sp = dynamic_cast <Simple_Selector_Ptr_Const>(this )) return *sp < rhs;
353
+ throw " invalid selector base classes to compare" ;
354
+ return false ;
355
+ }
356
+
357
+ bool Simple_Selector::operator == (const Selector& rhs) const
358
+ {
359
+ if (Simple_Selector_Ptr_Const sp = dynamic_cast <Simple_Selector_Ptr_Const>(&rhs)) return *this == *sp;
360
+ return false ;
361
+ }
362
+
363
+ bool Simple_Selector::operator < (const Selector& rhs) const
364
+ {
365
+ if (Simple_Selector_Ptr_Const sp = dynamic_cast <Simple_Selector_Ptr_Const>(&rhs)) return *this < *sp;
366
+ return false ;
367
+ }
368
+
324
369
bool Simple_Selector::operator == (const Simple_Selector& rhs) const
325
370
{
326
- if (Pseudo_Selector_Ptr_Const lp = dynamic_cast <Pseudo_Selector_Ptr_Const>(this )) return *lp == rhs;
327
- if (Wrapped_Selector_Ptr_Const lw = dynamic_cast <Wrapped_Selector_Ptr_Const>(this )) return *lw == rhs;
328
- if (Attribute_Selector_Ptr_Const la = dynamic_cast <Attribute_Selector_Ptr_Const>(this )) return *la == rhs;
329
- if (is_ns_eq (ns (), rhs.ns ()))
330
- { return name () == rhs.name (); }
331
- return ns () == rhs.ns ();
371
+ Simple_Type type = simple_type ();
372
+ // dynamic cast is a bottleneck - use concrete type as types are final
373
+ if (type == PSEUDO_SEL /* Pseudo_Selector_Ptr_Const lp = dynamic_cast<Pseudo_Selector_Ptr_Const>(this) */ ) {
374
+ return *static_cast <Pseudo_Selector_Ptr_Const>(this ) == rhs;
375
+ }
376
+ else if (type == WRAPPED_SEL /* Wrapped_Selector_Ptr_Const lw = dynamic_cast<Wrapped_Selector_Ptr_Const>(this) */ ) {
377
+ return *static_cast <Wrapped_Selector_Ptr_Const>(this ) == rhs;
378
+ }
379
+ else if (type == ATTR_SEL /* Attribute_Selector_Ptr_Const la = dynamic_cast<Attribute_Selector_Ptr_Const>(this) */ ) {
380
+ return *static_cast <Attribute_Selector_Ptr_Const>(this ) == rhs;
381
+ }
382
+ else if (name_ == rhs.name_ )
383
+ { return is_ns_eq (ns_, rhs.ns_ ); }
384
+ else return false ;
332
385
}
333
386
334
387
bool Simple_Selector::operator < (const Simple_Selector& rhs) const
335
388
{
336
- if (Pseudo_Selector_Ptr_Const lp = dynamic_cast <Pseudo_Selector_Ptr_Const>(this )) return *lp == rhs;
337
- if (Wrapped_Selector_Ptr_Const lw = dynamic_cast <Wrapped_Selector_Ptr_Const>(this )) return *lw < rhs;
338
- if (Attribute_Selector_Ptr_Const la = dynamic_cast <Attribute_Selector_Ptr_Const>(this )) return *la < rhs;
339
- if (is_ns_eq (ns (), rhs.ns ()))
340
- { return name () < rhs.name (); }
341
- return ns () < rhs.ns ();
389
+ Simple_Type type = simple_type ();
390
+ // dynamic cast is a bottleneck - use concrete type as types are final
391
+ if (type == PSEUDO_SEL /* Pseudo_Selector_Ptr_Const lp = dynamic_cast<Pseudo_Selector_Ptr_Const>(this) */ ) {
392
+ return *static_cast <Pseudo_Selector_Ptr_Const>(this ) < rhs;
393
+ }
394
+ else if (type == WRAPPED_SEL /* Wrapped_Selector_Ptr_Const lw = dynamic_cast<Wrapped_Selector_Ptr_Const>(this) */ ) {
395
+ return *static_cast <Wrapped_Selector_Ptr_Const>(this ) < rhs;
396
+ }
397
+ else if (type == ATTR_SEL /* Attribute_Selector_Ptr_Const la = dynamic_cast<Attribute_Selector_Ptr_Const>(this) */ ) {
398
+ return *static_cast <Attribute_Selector_Ptr_Const>(this ) < rhs;
399
+ }
400
+ if (is_ns_eq (ns_, rhs.ns_ ))
401
+ { return name_ < rhs.name_ ; }
402
+ return ns_ < rhs.ns_ ;
342
403
}
343
404
344
405
bool Selector_List::operator == (const Selector& rhs) const
@@ -394,6 +455,21 @@ namespace Sass {
394
455
return true ;
395
456
}
396
457
458
+ bool Selector_List::operator < (const Selector& rhs) const
459
+ {
460
+ if (Selector_List_Ptr_Const sp = dynamic_cast <Selector_List_Ptr_Const>(&rhs)) return *this < *sp;
461
+ return false ;
462
+ }
463
+
464
+ bool Selector_List::operator < (const Selector_List& rhs) const
465
+ {
466
+ if (this ->length () != rhs.length ()) return false ;
467
+ for (size_t i = 0 ; i < rhs.length (); i ++) {
468
+ if (!(*at (i) < *rhs.at (i))) return false ;
469
+ }
470
+ return true ;
471
+ }
472
+
397
473
Compound_Selector_Ptr Simple_Selector::unify_with (Compound_Selector_Ptr rhs, Context& ctx)
398
474
{
399
475
for (size_t i = 0 , L = rhs->length (); i < L; ++i)
@@ -539,12 +615,17 @@ namespace Sass {
539
615
540
616
bool Attribute_Selector::operator < (const Attribute_Selector& rhs) const
541
617
{
542
-
543
618
if (is_ns_eq (ns (), rhs.ns ())) {
544
619
if (name () == rhs.name ()) {
545
620
if (matcher () == rhs.matcher ()) {
546
- return &value () && &rhs.value () &&
547
- *value () < *rhs.value ();
621
+ bool no_lhs_val = value ().isNull ();
622
+ bool no_rhs_val = rhs.value ().isNull ();
623
+ if (no_lhs_val && no_rhs_val) {
624
+ return true ;
625
+ }
626
+ if (!no_lhs_val && !no_rhs_val) {
627
+ return *value () < *rhs.value ();
628
+ }
548
629
} else { return matcher () < rhs.matcher (); }
549
630
} else { return name () < rhs.name (); }
550
631
}
@@ -564,11 +645,25 @@ namespace Sass {
564
645
565
646
bool Attribute_Selector::operator == (const Attribute_Selector& rhs) const
566
647
{
567
- return (name () == rhs.name ())
648
+ // get optional value state
649
+ bool no_lhs_val = value ().isNull ();
650
+ bool no_rhs_val = rhs.value ().isNull ();
651
+ // both are null, therefore equal
652
+ if (no_lhs_val && no_rhs_val) {
653
+ return (name () == rhs.name ())
654
+ && (matcher () == rhs.matcher ())
655
+ && (is_ns_eq (ns (), rhs.ns ()));
656
+ }
657
+ // both are defined, evaluate
658
+ if (no_lhs_val == no_rhs_val) {
659
+ return (name () == rhs.name ())
568
660
&& (matcher () == rhs.matcher ())
569
661
&& (is_ns_eq (ns (), rhs.ns ()))
570
- && (&value () && &rhs.value ())
571
662
&& (*value () == *rhs.value ());
663
+ }
664
+ // not equal
665
+ return false ;
666
+
572
667
}
573
668
574
669
bool Attribute_Selector::operator == (const Simple_Selector& rhs) const
@@ -1471,7 +1566,7 @@ namespace Sass {
1471
1566
return final_result;
1472
1567
}
1473
1568
1474
- void Selector_List::populate_extends (Selector_List_Obj extendee, Context& ctx, ExtensionSubsetMap & extends)
1569
+ void Selector_List::populate_extends (Selector_List_Obj extendee, Context& ctx, Subset_Map & extends)
1475
1570
{
1476
1571
1477
1572
Selector_List_Ptr extender = this ;
@@ -1499,7 +1594,7 @@ namespace Sass {
1499
1594
compound_sel->is_optional (extendee->is_optional ());
1500
1595
1501
1596
for (size_t i = 0 , L = extender->length (); i < L; ++i) {
1502
- extends.put (compound_sel-> to_str_vec () , std::make_pair (&(*extender)[i], &compound_sel));
1597
+ extends.put (compound_sel, std::make_pair (&(*extender)[i], &compound_sel));
1503
1598
}
1504
1599
}
1505
1600
};
0 commit comments