@@ -197,47 +197,57 @@ extension String.UTF16View: BidirectionalCollection {
197
197
return idx. encoded ( offsetBy: - len) . _scalarAligned. _knownUTF8
198
198
}
199
199
200
+ @_effects ( releasenone)
200
201
public func index( _ i: Index , offsetBy n: Int ) -> Index {
201
- let i = _guts. ensureMatchingEncoding ( i)
202
+ var i = _guts. ensureMatchingEncoding ( i)
202
203
_precondition ( i <= endIndex, " String index is out of bounds " )
204
+
203
205
if _slowPath ( _guts. isForeign) {
204
206
return _foreignIndex ( i, offsetBy: n)
205
207
}
206
208
207
- if !_guts. isASCII { // We have ASCII fast paths below
208
- let threshold = (
209
- i == startIndex ? _breadcrumbStride / 2 : _breadcrumbStride)
210
- if n. magnitude < threshold {
211
- // Do not use breadcrumbs if directly computing the result is expected to
212
- // be cheaper.
213
- return _index ( i, offsetBy: n) . _knownUTF8
214
- }
209
+ if _guts. isASCII {
210
+ return Index (
211
+ _encodedOffset: i. _encodedOffset + n
212
+ ) . _scalarAligned. _encodingIndependent
213
+ }
214
+
215
+ i = _utf16AlignNativeIndex ( i)
216
+ let threshold = (
217
+ i == startIndex ? _breadcrumbStride / 2 : _breadcrumbStride)
218
+ if n. magnitude < threshold {
219
+ // Do not use breadcrumbs if directly computing the result is expected
220
+ // to be cheaper.
221
+ return _index ( i, offsetBy: n) . _knownUTF8
215
222
}
216
223
217
224
let lowerOffset = _nativeGetOffset ( for: i)
218
225
let result = _nativeGetIndex ( for: lowerOffset + n)
219
226
return result
220
227
}
221
228
229
+ @_effects ( releasenone)
222
230
public func index(
223
231
_ i: Index , offsetBy n: Int , limitedBy limit: Index
224
232
) -> Index ? {
225
- let limit = _guts. ensureMatchingEncoding ( limit)
233
+ var limit = _guts. ensureMatchingEncoding ( limit)
226
234
guard _fastPath ( limit <= endIndex) else { return index ( i, offsetBy: n) }
227
235
228
- let i = _guts. ensureMatchingEncoding ( i)
236
+ var i = _guts. ensureMatchingEncoding ( i)
229
237
_precondition ( i <= endIndex, " String index is out of bounds " )
230
238
231
239
if _slowPath ( _guts. isForeign) {
232
240
return _foreignIndex ( i, offsetBy: n, limitedBy: limit)
233
241
}
234
242
235
243
if !_guts. isASCII { // We have ASCII fast paths below
244
+ limit = _utf16AlignNativeIndex ( limit)
245
+ i = _utf16AlignNativeIndex ( i)
236
246
let threshold = (
237
247
_breadcrumbStride + ( i == startIndex ? 0 : _breadcrumbStride / 2 ) )
238
248
if n. magnitude < threshold {
239
- // Do not use breadcrumbs if directly computing the result is expected to
240
- // be cheaper.
249
+ // Do not use breadcrumbs if directly computing the result is expected
250
+ // to be cheaper.
241
251
return _index ( i, offsetBy: n, limitedBy: limit) ? . _knownUTF8
242
252
}
243
253
}
@@ -351,8 +361,8 @@ extension String.UTF16View: BidirectionalCollection {
351
361
for range: Range < Index > ,
352
362
from start: Index
353
363
) -> Range < Int > {
354
- let lower = _guts. ensureMatchingEncoding ( range. lowerBound)
355
- let upper = _guts. ensureMatchingEncoding ( range. upperBound)
364
+ var lower = _guts. ensureMatchingEncoding ( range. lowerBound)
365
+ var upper = _guts. ensureMatchingEncoding ( range. upperBound)
356
366
_internalInvariant ( _guts. hasMatchingEncoding ( start) )
357
367
358
368
_precondition (
@@ -378,6 +388,8 @@ extension String.UTF16View: BidirectionalCollection {
378
388
}
379
389
380
390
if utf8Distance. magnitude <= _breadcrumbStride / 2 {
391
+ lower = _utf16AlignNativeIndex ( lower)
392
+ upper = _utf16AlignNativeIndex ( upper)
381
393
let lowerOffset = distance ( from: start, to: lower)
382
394
let distance = _utf16Distance ( from: lower, to: upper)
383
395
return Range ( uncheckedBounds: ( lowerOffset, lowerOffset + distance) )
0 commit comments