@@ -16,25 +16,49 @@ import SwiftShims
16
16
//memcmp fast path for comparing ascii strings. rdar://problem/37473470
17
17
@inline ( never) // @outlined
18
18
@effects ( readonly)
19
- @_versioned internal
19
+ @_versioned // @opaque
20
+ internal
20
21
func _compareUnicode(
21
22
_ lhs: _StringGuts . _RawBitPattern , _ rhs: _StringGuts . _RawBitPattern
22
23
) -> Int {
23
24
let left = _StringGuts ( rawBits: lhs)
24
25
let right = _StringGuts ( rawBits: rhs)
25
- return left. _compare ( right)
26
+
27
+ if _slowPath ( !left. _isContiguous || !right. _isContiguous) {
28
+ if !left. _isContiguous {
29
+ return left. _asOpaque ( ) . _compareOpaque ( right) . rawValue
30
+ } else {
31
+ return right. _asOpaque ( ) . _compareOpaque ( left) . flipped. rawValue
32
+ }
33
+ }
34
+
35
+ return left. _compareContiguous ( right)
26
36
}
27
37
28
38
@inline ( never) // @outlined
29
39
@effects ( readonly)
30
- @_versioned internal
40
+ @_versioned // @opaque
41
+ internal
31
42
func _compareUnicode(
32
43
_ lhs: _StringGuts . _RawBitPattern , _ leftRange: Range < Int > ,
33
44
_ rhs: _StringGuts . _RawBitPattern , _ rightRange: Range < Int >
34
45
) -> Int {
35
46
let left = _StringGuts ( rawBits: lhs)
36
47
let right = _StringGuts ( rawBits: rhs)
37
- return left. _compare ( leftRange, right, rightRange)
48
+
49
+ if _slowPath ( !left. _isContiguous || !right. _isContiguous) {
50
+ if !left. _isContiguous {
51
+ return left. _asOpaque ( ) [ leftRange] . _compareOpaque (
52
+ right, rightRange
53
+ ) . rawValue
54
+ } else {
55
+ return right. _asOpaque ( ) [ rightRange] . _compareOpaque (
56
+ left, leftRange
57
+ ) . flipped. rawValue
58
+ }
59
+ }
60
+
61
+ return left. _compareContiguous ( leftRange, right, rightRange)
38
62
}
39
63
40
64
//
@@ -484,61 +508,68 @@ extension _UnmanagedString where CodeUnit == UInt8 {
484
508
public extension _StringGuts {
485
509
@inline ( __always)
486
510
public
487
- func _compare( _ other: _StringGuts ) -> Int {
488
- let selfRange = Range < Int > ( uncheckedBounds: ( 0 , self . count) )
489
- let otherRange = Range < Int > ( uncheckedBounds: ( 0 , other. count) )
490
- return _compare ( selfRange, other, otherRange)
511
+ func _compareContiguous( _ other: _StringGuts ) -> Int {
512
+ _sanityCheck ( self . _isContiguous && other. _isContiguous)
513
+ switch ( self . isASCII, other. isASCII) {
514
+ case ( true , true ) :
515
+ fatalError ( " Should have hit the ascii comp in StringComparable.compare() " )
516
+ case ( true , false ) :
517
+ return self . _unmanagedASCIIView. _compareStringsPreLoop (
518
+ other: other. _unmanagedUTF16View
519
+ ) . rawValue
520
+ case ( false , true ) :
521
+ // Same compare, just invert result
522
+ return other. _unmanagedASCIIView. _compareStringsPreLoop (
523
+ other: self . _unmanagedUTF16View
524
+ ) . flipped. rawValue
525
+ case ( false , false ) :
526
+ return self . _unmanagedUTF16View. _compareStringsPreLoop (
527
+ other: other. _unmanagedUTF16View
528
+ ) . rawValue
529
+ }
491
530
}
492
531
493
532
@inline ( __always)
494
533
public
495
- func _compare (
534
+ func _compareContiguous (
496
535
_ selfRange: Range < Int > ,
497
536
_ other: _StringGuts ,
498
537
_ otherRange: Range < Int >
499
538
) -> Int {
500
- if _slowPath (
501
- !self . _isContiguous || !other. _isContiguous
502
- ) {
503
- if !self . _isContiguous {
504
- return self . _asOpaque ( ) . _compareOpaque (
505
- selfRange, other, otherRange
506
- ) . rawValue
507
- } else {
508
- return other. _asOpaque ( ) . _compareOpaque (
509
- otherRange, self , selfRange
510
- ) . flipped. rawValue
511
- }
512
- }
513
-
514
- switch ( self . isASCII, other. isASCII) {
515
- case ( true , true ) :
516
- fatalError ( " Should have hit the ascii comp in StringComparable.compare() " )
517
- case ( true , false ) :
518
- return self . _unmanagedASCIIView [ selfRange] . _compareStringsPreLoop (
519
- other: other. _unmanagedUTF16View [ otherRange]
520
- ) . rawValue
521
- case ( false , true ) :
522
- // Same compare, just invert result
523
- return other. _unmanagedASCIIView [ otherRange] . _compareStringsPreLoop (
524
- other: self . _unmanagedUTF16View [ selfRange]
525
- ) . flipped. rawValue
526
- case ( false , false ) :
527
- return self . _unmanagedUTF16View [ selfRange] . _compareStringsPreLoop (
528
- other: other. _unmanagedUTF16View [ otherRange]
529
- ) . rawValue
530
- }
539
+ _sanityCheck ( self . _isContiguous && other. _isContiguous)
540
+ switch ( self . isASCII, other. isASCII) {
541
+ case ( true , true ) :
542
+ fatalError ( " Should have hit the ascii comp in StringComparable.compare() " )
543
+ case ( true , false ) :
544
+ return self . _unmanagedASCIIView [ selfRange] . _compareStringsPreLoop (
545
+ other: other. _unmanagedUTF16View [ otherRange]
546
+ ) . rawValue
547
+ case ( false , true ) :
548
+ // Same compare, just invert result
549
+ return other. _unmanagedASCIIView [ otherRange] . _compareStringsPreLoop (
550
+ other: self . _unmanagedUTF16View [ selfRange]
551
+ ) . flipped. rawValue
552
+ case ( false , false ) :
553
+ return self . _unmanagedUTF16View [ selfRange] . _compareStringsPreLoop (
554
+ other: other. _unmanagedUTF16View [ otherRange]
555
+ ) . rawValue
556
+ }
531
557
}
532
558
}
533
559
534
560
extension _UnmanagedOpaqueString {
535
- @inline ( never)
561
+ @inline ( never) // @outlined
562
+ @_versioned
563
+ internal
564
+ func _compareOpaque( _ other: _StringGuts ) -> _Ordering {
565
+ return self . _compareOpaque ( other, 0 ..< other. count)
566
+ }
567
+
568
+ @inline ( never) // @outlined
536
569
@_versioned
537
570
internal
538
571
func _compareOpaque(
539
- _ selfRange: Range < Int > ,
540
- _ other: _StringGuts ,
541
- _ otherRange: Range < Int >
572
+ _ other: _StringGuts , _ otherRange: Range < Int >
542
573
) -> _Ordering {
543
574
//
544
575
// Do a fast Latiny comparison loop; bail if that proves insufficient.
@@ -548,11 +579,10 @@ extension _UnmanagedOpaqueString {
548
579
// termination of an all-ASCII file loaded by String.init(contentsOfFile:).
549
580
//
550
581
551
-
552
- let selfCount = selfRange. count
582
+ let selfCount = self . count
553
583
let otherCount = otherRange. count
554
584
let count = Swift . min ( selfCount, otherCount)
555
- let idx = self [ selfRange ] . _findDiffIdx ( other, otherRange)
585
+ let idx = self . _findDiffIdx ( other, otherRange)
556
586
if idx == count {
557
587
return _lexicographicalCompare ( selfCount, otherCount)
558
588
}
0 commit comments