|
11 | 11 |
|
12 | 12 | extension _StringGuts {
|
13 | 13 | @inline(__always)
|
14 |
| - @available(SwiftStdlib 5.7, *) |
15 |
| - internal func roundDownToNearestWord(_ i: String.Index) -> String.Index { |
16 |
| - _internalInvariant(i._isScalarAligned) |
17 |
| - _internalInvariant(hasMatchingEncoding(i)) |
| 14 | + internal func roundDownToNearestWord( |
| 15 | + _ i: String._WordView.Index |
| 16 | + ) -> String._WordView.Index { |
18 | 17 | _internalInvariant(i._encodedOffset <= count)
|
19 | 18 |
|
20 |
| - if _fastPath(i._isWordAligned) { |
21 |
| - return i |
22 |
| - } |
23 |
| - |
24 | 19 | let offset = i._encodedOffset
|
25 | 20 |
|
26 | 21 | if offset == 0 || offset == count {
|
27 |
| - return i._wordAligned |
| 22 | + return i |
28 | 23 | }
|
29 | 24 |
|
30 | 25 | return _slowRoundDownToNearestWord(i)
|
31 | 26 | }
|
32 | 27 |
|
33 | 28 | @inline(never)
|
34 |
| - @available(SwiftStdlib 5.7, *) |
35 |
| - internal func _slowRoundDownToNearestWord(_ i: String.Index) -> String.Index { |
36 |
| - let words = String._WordView(self) |
37 |
| - |
| 29 | + internal func _slowRoundDownToNearestWord( |
| 30 | + _ i: String._WordView.Index |
| 31 | + ) -> String._WordView.Index { |
38 | 32 | let offset = i._encodedOffset
|
39 |
| - let start = offset &- words._uncheckedIndex(before: i)._encodedOffset |
40 |
| - let startIndex = String.Index(_encodedOffset: start)._wordAligned |
41 |
| - let stride = words._uncheckedIndex(after: startIndex)._encodedOffset |
| 33 | + let start = _opaquePreviousWordIndex(endingAt: offset) |
| 34 | + let stride = _opaqueNextWordIndex(startingAt: start) &- start |
42 | 35 | _internalInvariant(offset <= start + stride, "Word breaking inconsistency")
|
43 | 36 |
|
44 | 37 | if offset >= start + stride {
|
45 |
| - return i._wordAligned |
| 38 | + return i |
46 | 39 | }
|
47 | 40 |
|
48 |
| - let r = String.Index(_encodedOffset: start)._wordAligned |
49 |
| - return markEncoding(r) |
| 41 | + return String._WordView.Index(_encodedOffset: start) |
| 42 | + } |
| 43 | + |
| 44 | + @inline(never) |
| 45 | + @_effects(releasenone) |
| 46 | + internal func _opaqueNextWordIndex(startingAt i: Int) -> Int { |
| 47 | + if _slowPath(isForeign) { |
| 48 | + return _foreignOpaqueNextWordIndex(startingAt: i) |
| 49 | + } |
| 50 | + |
| 51 | + return withFastUTF8 { utf8 in |
| 52 | + nextWordBoundary(startingAt: i) { |
| 53 | + _internalInvariant($0 >= 0) |
| 54 | + |
| 55 | + guard $0 < utf8.count else { |
| 56 | + return nil |
| 57 | + } |
| 58 | + |
| 59 | + let (scalar, len) = _decodeScalar(utf8, startingAt: $0) |
| 60 | + return (scalar, $0 &+ len) |
| 61 | + } |
| 62 | + } |
| 63 | + } |
| 64 | + |
| 65 | + internal func _foreignOpaqueNextWordIndex(startingAt i: Int) -> Int { |
| 66 | +#if _runtime(_ObjC) |
| 67 | + return nextWordBoundary(startingAt: i) { |
| 68 | + _internalInvariant($0 >= 0) |
| 69 | + |
| 70 | + guard $0 < count else { |
| 71 | + return nil |
| 72 | + } |
| 73 | + |
| 74 | + let scalars = String.UnicodeScalarView(self) |
| 75 | + let idx = String.Index(_encodedOffset: $0) |
| 76 | + |
| 77 | + let scalar = scalars[idx] |
| 78 | + let nextIndex = scalars.index(after: idx) |
| 79 | + |
| 80 | + return (scalar, nextIndex._encodedOffset) |
| 81 | + } |
| 82 | +#else |
| 83 | + fatalError("No foreign strings on this platform in this version of Swift.") |
| 84 | +#endif |
| 85 | + } |
| 86 | + |
| 87 | + internal func _opaquePreviousWordIndex(endingAt i: Int) -> Int { |
| 88 | + if _slowPath(isForeign) { |
| 89 | + return _foreignOpaquePreviousWordIndex(endingAt: i) |
| 90 | + } |
| 91 | + |
| 92 | + return withFastUTF8 { utf8 in |
| 93 | + previousWordBoundary(endingAt: i) { |
| 94 | + _internalInvariant($0 <= count) |
| 95 | + |
| 96 | + guard $0 > 0 else { |
| 97 | + return nil |
| 98 | + } |
| 99 | + |
| 100 | + let (scalar, len) = _decodeScalar(utf8, endingAt: $0) |
| 101 | + return (scalar, $0 &- len) |
| 102 | + } |
| 103 | + } |
| 104 | + } |
| 105 | + |
| 106 | + @inline(never) |
| 107 | + internal func _foreignOpaquePreviousWordIndex(endingAt i: Int) -> Int { |
| 108 | + #if _runtime(_ObjC) |
| 109 | + return previousWordBoundary(endingAt: i) { |
| 110 | + _internalInvariant($0 <= count) |
| 111 | + |
| 112 | + guard $0 > 0 else { |
| 113 | + return nil |
| 114 | + } |
| 115 | + |
| 116 | + let scalars = String.UnicodeScalarView(self) |
| 117 | + let idx = String.Index(_encodedOffset: $0) |
| 118 | + |
| 119 | + let previousIndex = scalars.index(before: idx) |
| 120 | + let scalar = scalars[previousIndex] |
| 121 | + |
| 122 | + return (scalar, previousIndex._encodedOffset) |
| 123 | + } |
| 124 | +#else |
| 125 | + fatalError("No foreign strings on this platform in this version of Swift.") |
| 126 | +#endif |
50 | 127 | }
|
51 | 128 | }
|
52 | 129 |
|
@@ -77,10 +154,9 @@ internal struct _WordBreakingState {
|
77 | 154 | var shouldBreakRI = false
|
78 | 155 | }
|
79 | 156 |
|
80 |
| -@available(SwiftStdlib 5.7, *) |
81 |
| -extension String._WordView { |
| 157 | +extension _StringGuts { |
82 | 158 | // Returns the stride of the next word at the previous boundary offset.
|
83 |
| - internal func nextBoundary( |
| 159 | + internal func nextWordBoundary( |
84 | 160 | startingAt index: Int,
|
85 | 161 | nextScalar: (Int) -> (scalar: Unicode.Scalar, end: Int)?
|
86 | 162 | ) -> Int {
|
@@ -109,7 +185,7 @@ extension String._WordView {
|
109 | 185 | }
|
110 | 186 |
|
111 | 187 | // Returns the stride of the previous word at the current boundary offset.
|
112 |
| - internal func previousBoundary( |
| 188 | + internal func previousWordBoundary( |
113 | 189 | endingAt index: Int,
|
114 | 190 | previousScalar: (Int) -> (scalar: Unicode.Scalar, start: Int)?
|
115 | 191 | ) -> Int {
|
@@ -145,8 +221,7 @@ extension String._WordView {
|
145 | 221 | }
|
146 | 222 | }
|
147 | 223 |
|
148 |
| -@available(SwiftStdlib 5.7, *) |
149 |
| -extension String._WordView { |
| 224 | +extension _StringGuts { |
150 | 225 | // The "algorithm" that determines whether or not we should break between
|
151 | 226 | // certain word break properties.
|
152 | 227 | //
|
@@ -345,8 +420,7 @@ extension String._WordView {
|
345 | 420 | }
|
346 | 421 | }
|
347 | 422 |
|
348 |
| -@available(SwiftStdlib 5.7, *) |
349 |
| -extension String._WordView { |
| 423 | +extension _StringGuts { |
350 | 424 | // The "algorithm" that determines whether or not we should break between
|
351 | 425 | // certain word break properties.
|
352 | 426 | //
|
|
0 commit comments