Skip to content

Commit 588e296

Browse files
committed
WIP: Attempt at re-organizing a little bit of comparison code
1 parent 0661de2 commit 588e296

File tree

1 file changed

+77
-47
lines changed

1 file changed

+77
-47
lines changed

stdlib/public/core/StringComparison.swift

Lines changed: 77 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -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
2021
func _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
3142
func _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 {
484508
public 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

534560
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
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

Comments
 (0)