16
16
//
17
17
//===----------------------------------------------------------------------===//
18
18
19
- // FIXME(ABI)#72 : The UTF-8 string view should conform to
20
- // `BidirectionalCollection`.
21
-
22
- // FIXME(ABI)#73 : The UTF-8 string view should have a custom iterator type to
23
- // allow performance optimizations of linear traversals.
24
-
25
19
extension String {
26
20
/// A view of a string's contents as a collection of UTF-8 code units.
27
21
///
@@ -102,11 +96,24 @@ extension String {
102
96
CustomStringConvertible ,
103
97
CustomDebugStringConvertible {
104
98
99
+ /// Underlying UTF-16-compatible representation
105
100
@_versioned
106
101
internal let _core : _StringCore
107
102
108
- init ( _ _core: _StringCore ) {
103
+ /// Distances to `(startIndex, endIndex)` from the endpoints of _core,
104
+ /// measured in UTF-8 code units.
105
+ ///
106
+ /// Note: this is *only* here to support legacy Swift3-style slicing where
107
+ /// `s.utf8[i..<j]` produces a `String.UTF8View`, and should be removed when
108
+ /// those semantics are no longer supported.
109
+ @_versioned
110
+ internal let _legacyOffsets : ( start: Int8 , end: Int8 )
111
+
112
+ init ( _ _core: _StringCore ,
113
+ legacyOffsets: ( Int , Int ) = ( 0 , 0 )
114
+ ) {
109
115
self . _core = _core
116
+ self . _legacyOffsets = ( Int8 ( legacyOffsets. 0 ) , Int8 ( legacyOffsets. 1 ) )
110
117
}
111
118
112
119
public typealias Index = String . Index
@@ -117,15 +124,25 @@ extension String {
117
124
///
118
125
/// If the UTF-8 view is empty, `startIndex` is equal to `endIndex`.
119
126
public var startIndex : Index {
120
- return _index ( atEncodedOffset: _core. startIndex)
127
+ let r = _index ( atEncodedOffset: _core. startIndex)
128
+ if _legacyOffsets. start == 0 { return r }
129
+ return index ( r, offsetBy: numericCast ( _legacyOffsets. start) )
121
130
}
122
131
123
132
/// The "past the end" position---that is, the position one
124
133
/// greater than the last valid subscript argument.
125
134
///
126
135
/// In an empty UTF-8 view, `endIndex` is equal to `startIndex`.
127
136
public var endIndex : Index {
128
- return Index ( encodedOffset: _core. endIndex)
137
+ var r = Index ( encodedOffset: _core. endIndex)
138
+ switch _legacyOffsets. end {
139
+ case 0 : return r
140
+ case - 3 : r = index ( before: r) ; fallthrough
141
+ case - 2 : r = index ( before: r) ; fallthrough
142
+ case - 1 : r = index ( before: r) ; fallthrough
143
+ default : break
144
+ }
145
+ return r
129
146
}
130
147
131
148
@_versioned
@@ -231,7 +248,7 @@ extension String {
231
248
case . valid( let u16) :
232
249
u8 = Unicode . UTF8. transcode (
233
250
u16, from: Unicode . UTF16. self) . _unsafelyUnwrappedUnchecked
234
- case . error( let stride ) :
251
+ case . error:
235
252
u8 = Unicode . UTF8. encodedReplacementCharacter
236
253
case . emptyInput:
237
254
_preconditionFailure ( " index out of bounds " )
@@ -631,7 +648,6 @@ extension String.UTF8View {
631
648
}
632
649
}
633
650
634
- /*
635
651
//===--- Slicing Support --------------------------------------------------===//
636
652
/// In Swift 3.2, in the absence of type context,
637
653
///
@@ -641,17 +657,30 @@ extension String.UTF8View {
641
657
/// Swift-3-only `subscript` overload that continues to produce
642
658
/// `String.UTF8View`.
643
659
extension String . UTF8View {
660
+ public typealias SubSequence = BidirectionalSlice < String . UTF8View >
661
+
644
662
@available ( swift, introduced: 4 )
645
663
public subscript( r: Range < Index > ) -> String . UTF8View . SubSequence {
646
664
return String . UTF8View. SubSequence ( base: self , bounds: r)
647
665
}
648
666
649
667
@available ( swift, obsoleted: 4 )
650
- public subscript(bounds: Range<Index>) -> String.UTF8View {
651
- var r = self
652
- r._startIndex = bounds.lowerBound
653
- r._endIndex = bounds.upperBound
654
- return r
668
+ public subscript( r: Range < Index > ) -> String . UTF8View {
669
+ if r. upperBound. _transcodedOffset == 0 {
670
+ return String . UTF8View (
671
+ _core [ r. lowerBound. encodedOffset..< r. upperBound. encodedOffset] ,
672
+ legacyOffsets: ( r. lowerBound. _transcodedOffset, 0 ) )
673
+ }
674
+
675
+ let b0 = r. upperBound. _cache. utf8!. first!
676
+ let scalarLength8 = ( ~ b0) . leadingZeroBitCount
677
+ let scalarLength16 = scalarLength8 == 4 ? 2 : 1
678
+ let coreEnd = r. upperBound. encodedOffset + scalarLength16
679
+ return String . UTF8View (
680
+ _core [ r. lowerBound. encodedOffset..< coreEnd] ,
681
+ legacyOffsets: (
682
+ r. lowerBound. _transcodedOffset,
683
+ r. upperBound. _transcodedOffset - scalarLength8) )
655
684
}
656
685
657
686
@available ( swift, obsoleted: 4 )
@@ -660,4 +689,3 @@ extension String.UTF8View {
660
689
}
661
690
}
662
691
663
- */
0 commit comments