@@ -16,25 +16,49 @@ import SwiftShims
1616//memcmp fast path for comparing ascii strings. rdar://problem/37473470
1717@inline ( never) // @outlined
1818@effects ( readonly)
19- @_versioned internal
19+ @_versioned // @opaque
20+ internal
2021func _compareUnicode(
2122 _ lhs: _StringGuts . _RawBitPattern , _ rhs: _StringGuts . _RawBitPattern
2223) -> Int {
2324 let left = _StringGuts ( rawBits: lhs)
2425 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)
2636}
2737
2838@inline ( never) // @outlined
2939@effects ( readonly)
30- @_versioned internal
40+ @_versioned // @opaque
41+ internal
3142func _compareUnicode(
3243 _ lhs: _StringGuts . _RawBitPattern , _ leftRange: Range < Int > ,
3344 _ rhs: _StringGuts . _RawBitPattern , _ rightRange: Range < Int >
3445) -> Int {
3546 let left = _StringGuts ( rawBits: lhs)
3647 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)
3862}
3963
4064//
@@ -484,61 +508,68 @@ extension _UnmanagedString where CodeUnit == UInt8 {
484508public extension _StringGuts {
485509 @inline ( __always)
486510 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+ }
491530 }
492531
493532 @inline ( __always)
494533 public
495- func _compare (
534+ func _compareContiguous (
496535 _ selfRange: Range < Int > ,
497536 _ other: _StringGuts ,
498537 _ otherRange: Range < Int >
499538 ) -> 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+ }
531557 }
532558}
533559
534560extension _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
536569 @_versioned
537570 internal
538571 func _compareOpaque(
539- _ selfRange: Range < Int > ,
540- _ other: _StringGuts ,
541- _ otherRange: Range < Int >
572+ _ other: _StringGuts , _ otherRange: Range < Int >
542573 ) -> _Ordering {
543574 //
544575 // Do a fast Latiny comparison loop; bail if that proves insufficient.
@@ -548,11 +579,10 @@ extension _UnmanagedOpaqueString {
548579 // termination of an all-ASCII file loaded by String.init(contentsOfFile:).
549580 //
550581
551-
552- let selfCount = selfRange. count
582+ let selfCount = self . count
553583 let otherCount = otherRange. count
554584 let count = Swift . min ( selfCount, otherCount)
555- let idx = self [ selfRange ] . _findDiffIdx ( other, otherRange)
585+ let idx = self . _findDiffIdx ( other, otherRange)
556586 if idx == count {
557587 return _lexicographicalCompare ( selfCount, otherCount)
558588 }
0 commit comments