[Backtracing] Also try CFStringGetCharactersPtr when converting CFStrings.

We already try using `CFStringGetCStringPtr` to see if we can get ASCII;
we should also try `CFStringGetCharactersPtr` as the native encoding of
`CFNSString` is very often UTF-16.  While we're at it, try asking explicitly
for UTF-8 as well.  That won't work for `CFNSString` because AFAIK it's
currently never encoded that way, but it might work if something hands us
a Swift-backed string or if some future implementation of `CFString`
happens to support UTF-8 encoded data.

rdar://124913332
This commit is contained in:
Alastair Houghton
2024-11-14 14:43:24 +00:00
parent 0e3e9efcd3
commit 348a325d2a

View File

@@ -46,6 +46,9 @@ private func symbol<T>(_ handle: UnsafeMutableRawPointer, _ name: String) -> T {
return unsafeBitCast(result, to: T.self)
}
// Define UniChar
typealias UniChar = UInt16
private enum Sym {
// CRCopySanitizedPath
static let CRCopySanitizedPath: @convention(c) (CFString, CFIndex) -> CFString =
@@ -130,6 +133,9 @@ private enum Sym {
UnsafeMutableRawPointer?, CFIndex,
UnsafeMutablePointer<CFIndex>?) -> CFIndex =
symbol(coreFoundationHandle, "CFStringGetBytes")
static let CFStringGetCharactersPtr:
@convention(c) (CFString) -> UnsafePointer<UniChar>? =
symbol(coreFoundationHandle, "CFStringGetCharactersPtr")
}
// .. Core Foundation miscellany ...............................................
@@ -161,6 +167,11 @@ internal func CFStringGetCStringPtr(_ s: CFString,
return Sym.CFStringGetCStringPtr(s, encoding)
}
internal func CFStringGetCharactersPtr(_ s: CFString)
-> UnsafePointer<UniChar>? {
return Sym.CFStringGetCharactersPtr(s);
}
internal func CFStringGetBytes(_ s: CFString,
_ range: CFRange,
_ encoding: CFStringEncoding,
@@ -199,8 +210,15 @@ private func fromCFString(_ cf: CFString) -> String {
if let ptr = CFStringGetCStringPtr(cf,
CFStringBuiltInEncodings.ASCII.rawValue) {
return String(decoding: UnsafeRawBufferPointer(start: ptr, count: length),
as: UTF8.self)
let buffer = UnsafeRawBufferPointer(start: ptr, count: length)
return String(decoding: buffer, as: UTF8.self)
} else if let ptr = CFStringGetCharactersPtr(cf) {
let buffer = UnsafeBufferPointer(start: ptr, count: length)
return String(decoding: buffer, as: UTF16.self)
} else if let ptr = CFStringGetCStringPtr(cf,
CFStringBuiltInEncodings.UTF8.rawValue) {
let buffer = UnsafeRawBufferPointer(start: ptr, count: length)
return String(decoding: buffer, as: UTF8.self)
} else {
var byteLen = CFIndex(0)