Skip to content

Commit cdf9a8b

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-next
2 parents 78f4401 + 5fba88c commit cdf9a8b

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

stdlib/public/core/StringBridge.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,26 @@ internal func _cocoaStringCopyUTF8(
9090
return len == converted ? count : nil
9191
}
9292

93+
@_effects(readonly)
94+
internal func _cocoaStringUTF8Count(
95+
_ target: _CocoaString,
96+
range: Range<Int>
97+
) -> Int? {
98+
var count = 0
99+
let len = _stdlib_binary_CFStringGetLength(target)
100+
let converted = _swift_stdlib_CFStringGetBytes(
101+
target,
102+
_swift_shims_CFRange(location: range.startIndex, length: range.count),
103+
kCFStringEncodingUTF8,
104+
0,
105+
0,
106+
UnsafeMutablePointer<UInt8>(Builtin.inttoptr_Word(0._builtinWordValue)),
107+
0,
108+
&count
109+
)
110+
return converted == len ? count : nil
111+
}
112+
93113
@_effects(readonly)
94114
internal func _cocoaStringCompare(
95115
_ string: _CocoaString, _ other: _CocoaString

stdlib/public/core/StringUTF8View.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,14 +470,31 @@ extension String.UTF8View {
470470
@_effects(releasenone)
471471
internal func _foreignDistance(from i: Index, to j: Index) -> Int {
472472
_internalInvariant(_guts.isForeign)
473+
474+
#if _runtime(_ObjC)
475+
// Currently, foreign means NSString
476+
if let count = _cocoaStringUTF8Count(
477+
_guts._object.cocoaObject,
478+
range: i._encodedOffset ..< j._encodedOffset
479+
) {
480+
//_cocoaStringUTF8Count gave us the scalar aligned count, but we still
481+
//need to compensate for sub-scalar indexing, e.g. if `i` is in the middle
482+
//of a two-byte UTF8 scalar.
483+
let refinedCount = count - (i.transcodedOffset + j.transcodedOffset)
484+
_internalInvariant(refinedCount == _distance(from: i, to: j))
485+
return refinedCount
486+
}
487+
#endif
488+
473489
return _distance(from: i, to: j)
490+
474491
}
475492

476493
@usableFromInline @inline(never)
477494
@_effects(releasenone)
478495
internal func _foreignCount() -> Int {
479496
_internalInvariant(_guts.isForeign)
480-
return _distance(from: startIndex, to: endIndex)
497+
return _foreignDistance(from: startIndex, to: endIndex)
481498
}
482499
}
483500

0 commit comments

Comments
 (0)