Merge pull request #68423 from glessard/se0405-take2

[se-0405] rename `String.init(validatingUTF8:)`
This commit is contained in:
Guillaume Lessard
2024-01-22 09:29:21 -08:00
committed by GitHub
11 changed files with 102 additions and 44 deletions

View File

@@ -16,7 +16,7 @@ public enum SwiftRuntime {
private static func _metadataKind<T>(of value: T) -> UnsafePointer<CChar>
public static func metadataKind<T>(of value: T) -> String {
return String(validatingUTF8: _metadataKind(of: value))!
return String(validatingCString: _metadataKind(of: value))!
}
}

View File

@@ -850,7 +850,7 @@ func _printDebuggingAdvice(_ fullTestName: String) {
#else
let interpreter = getenv("SWIFT_INTERPRETER")
if interpreter != nil {
if let interpreterCmd = String(validatingUTF8: interpreter!) {
if let interpreterCmd = String(validatingCString: interpreter!) {
invocation.insert(interpreterCmd, at: 0)
}
}

View File

@@ -405,7 +405,7 @@ public func spawnChild(_ args: [String])
childArgs.insert(CommandLine.arguments[0], at: 0)
let interpreter = getenv("SWIFT_INTERPRETER")
if interpreter != nil {
if let invocation = String(validatingUTF8: interpreter!) {
if let invocation = String(validatingCString: interpreter!) {
childArgs.insert(invocation, at: 0)
}
}

View File

@@ -64,7 +64,7 @@ internal func getAddressInfoForImage(atIndex i: UInt32) ->
debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") }
let header = unsafeBitCast(_dyld_get_image_header(i),
to: UnsafePointer<MachHeader>.self)
let name = String(validatingUTF8: _dyld_get_image_name(i)!)!
let name = String(validatingCString: _dyld_get_image_name(i)!)!
var size: UInt = 0
let address = getsegmentdata(header, "__TEXT", &size)
return (name, address, size)
@@ -111,7 +111,7 @@ internal func getReflectionInfoForImage(atIndex i: UInt32) -> ReflectionInfo? {
let capture = getSectionInfo("__swift5_capture", header)
let typeref = getSectionInfo("__swift5_typeref", header)
let reflstr = getSectionInfo("__swift5_reflstr", header)
return ReflectionInfo(imageName: String(validatingUTF8: imageName)!,
return ReflectionInfo(imageName: String(validatingCString: imageName)!,
fieldmd: fieldmd,
assocty: assocty,
builtin: builtin,
@@ -160,7 +160,7 @@ internal func getReflectionInfoForImage(atIndex i: UInt32) -> ReflectionInfo? {
return _getMetadataSection(UInt(i)).map { rawPointer in
let name = _getMetadataSectionName(rawPointer)
let metadataSection = rawPointer.bindMemory(to: MetadataSections.self, capacity: 1).pointee
return ReflectionInfo(imageName: String(validatingUTF8: name)!,
return ReflectionInfo(imageName: String(validatingCString: name)!,
fieldmd: Section(range: metadataSection.swift5_fieldmd),
assocty: Section(range: metadataSection.swift5_assocty),
builtin: Section(range: metadataSection.swift5_builtin),
@@ -302,7 +302,7 @@ internal func sendReflectionInfos() {
internal func printErrnoAndExit() {
debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") }
let errorCString = strerror(errno)!
let message = String(validatingUTF8: errorCString)! + "\n"
let message = String(validatingCString: errorCString)! + "\n"
let bytes = Array(message.utf8)
fwrite(bytes, 1, bytes.count, stderr)
fflush(stderr)

View File

@@ -435,7 +435,7 @@ public struct Backtrace: CustomStringConvertible, Sendable {
_dyld_process_info_for_each_segment(dyldInfo, machHeaderAddress) {
address, size, name in
if let name = String(validatingUTF8: name!), name == "__TEXT" {
if let name = String(validatingCString: name!), name == "__TEXT" {
endOfText = address + size
}
}

View File

@@ -124,6 +124,40 @@ extension String {
self = ""
}
/// Creates a new string by copying and validating the null-terminated UTF-8
/// data referenced by the given pointer.
///
/// This initializer does not try to repair ill-formed UTF-8 code unit
/// sequences. If any are found, the result of the initializer is `nil`.
///
/// The following example calls this initializer with pointers to the
/// contents of two different `CChar` arrays---the first with well-formed
/// UTF-8 code unit sequences and the second with an ill-formed sequence at
/// the end.
///
/// let validUTF8: [CChar] = [67, 97, 102, -61, -87, 0]
/// validUTF8.withUnsafeBufferPointer { ptr in
/// let s = String(validatingCString: ptr.baseAddress!)
/// print(s)
/// }
/// // Prints "Optional("Café")"
///
/// let invalidUTF8: [CChar] = [67, 97, 102, -61, 0]
/// invalidUTF8.withUnsafeBufferPointer { ptr in
/// let s = String(validatingCString: ptr.baseAddress!)
/// print(s)
/// }
/// // Prints "nil"
///
/// - Parameter nullTerminatedUTF8:
/// A pointer to a null-terminated UTF-8 code sequence.
@inlinable
@_alwaysEmitIntoClient
public init?(validatingCString nullTerminatedUTF8: UnsafePointer<CChar>) {
// FIXME: https://github.com/apple/swift/issues/68433 (rdar://115296219)
self.init(validatingUTF8: nullTerminatedUTF8)
}
/// Creates a new string by copying and validating the null-terminated UTF-8
/// data referenced by the given pointer.
///
@@ -149,7 +183,11 @@ extension String {
/// }
/// // Prints "nil"
///
/// Note: This initializer is deprecated. Use
/// `String.init?(validatingCString:)` instead.
///
/// - Parameter cString: A pointer to a null-terminated UTF-8 code sequence.
@available(swift, deprecated: 6, renamed: "String.init(validatingCString:)")
public init?(validatingUTF8 cString: UnsafePointer<CChar>) {
let len = UTF8._nullCodeUnitOffset(in: cString)
guard let str = cString.withMemoryRebound(to: UInt8.self, capacity: len, {
@@ -162,37 +200,57 @@ extension String {
@inlinable
@_alwaysEmitIntoClient
public init?(validatingUTF8 cString: [CChar]) {
guard let length = cString.firstIndex(of: 0) else {
public init?(validatingCString nullTerminatedUTF8: [CChar]) {
guard let length = nullTerminatedUTF8.firstIndex(of: 0) else {
_preconditionFailure(
"input of String.init(validatingUTF8:) must be null-terminated"
"input of String.init(validatingCString:) must be null-terminated"
)
}
guard let string = cString.prefix(length).withUnsafeBufferPointer({
let string = nullTerminatedUTF8.prefix(length).withUnsafeBufferPointer {
$0.withMemoryRebound(to: UInt8.self, String._tryFromUTF8(_:))
})
else { return nil }
}
guard let string else { return nil }
self = string
}
@inlinable
@_alwaysEmitIntoClient
@available(*, deprecated, renamed: "String.init(validatingCString:)")
public init?(validatingUTF8 cString: [CChar]) {
self.init(validatingCString: cString)
}
@inlinable
@_alwaysEmitIntoClient
@available(*, deprecated, message: "Use a copy of the String argument")
public init?(validatingCString nullTerminatedUTF8: String) {
self = nullTerminatedUTF8.withCString(String.init(cString:))
}
@inlinable
@_alwaysEmitIntoClient
@available(*, deprecated, message: "Use a copy of the String argument")
public init?(validatingUTF8 cString: String) {
self = cString.withCString(String.init(cString:))
self.init(validatingCString: cString)
}
@inlinable
@_alwaysEmitIntoClient
@available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)")
public init?(validatingCString nullTerminatedUTF8: inout CChar) {
guard nullTerminatedUTF8 == 0 else {
_preconditionFailure(
"input of String.init(validatingUTF8:) must be null-terminated"
)
}
self = ""
}
@inlinable
@_alwaysEmitIntoClient
@available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)")
public init?(validatingUTF8 cString: inout CChar) {
guard cString == 0 else {
_preconditionFailure(
"input of String.init(validatingUTF8:) must be null-terminated"
)
}
self = ""
self.init(validatingCString: &cString)
}
/// Creates a new string by copying the null-terminated data referenced by

View File

@@ -196,7 +196,7 @@ public class AnyKeyPath: Hashable, _AppendKeyPath {
}
guard let ptr = _kvcKeyPathStringPtr else { return nil }
return String(validatingUTF8: ptr)
return String(validatingCString: ptr)
}
}

View File

@@ -355,7 +355,7 @@ internal func _adHocPrint_unlocked<T, TargetStream: TextOutputStream>(
target.write(")")
case .enum:
if let cString = _getEnumCaseName(value),
let caseName = String(validatingUTF8: cString) {
let caseName = String(validatingCString: cString) {
// Write the qualified type name in debugPrint.
if isDebugPrint {
printTypeName(mirror.subjectType)
@@ -390,7 +390,7 @@ internal func _adHocPrint_unlocked<T, TargetStream: TextOutputStream>(
} else {
// Fall back to the type or an opaque summary of the kind
if let cString = _opaqueSummary(mirror.subjectType),
let opaqueSummary = String(validatingUTF8: cString) {
let opaqueSummary = String(validatingCString: cString) {
target.write(opaqueSummary)
} else {
target.write(_typeName(mirror.subjectType, qualified: true))
@@ -532,7 +532,7 @@ internal func _dumpPrint_unlocked<T, TargetStream: TextOutputStream>(
case .`enum`:
target.write(_typeName(mirror.subjectType, qualified: true))
if let cString = _getEnumCaseName(value),
let caseName = String(validatingUTF8: cString) {
let caseName = String(validatingCString: cString) {
target.write(".")
target.write(caseName)
}

View File

@@ -66,7 +66,7 @@ internal func getChild<T>(of value: T, type: Any.Type, index: Int) -> (label: St
let value = _getChild(of: value, type: type, index: index, outName: &nameC, outFreeFunc: &freeFunc)
let name = nameC.flatMap({ String(validatingUTF8: $0) })
let name = nameC.flatMap({ String(validatingCString: $0) })
freeFunc?(nameC)
return (name, value)
}

View File

@@ -107,20 +107,20 @@ func expectEqualCString(_ lhs: UnsafePointer<UInt8>,
}
}
CStringTests.test("String.init(validatingUTF8:)") {
CStringTests.test("String.init(validatingCString:)") {
do {
let (s, dealloc) = getASCIIUTF8()
expectEqual("ab", String(validatingUTF8: bindAsCChar(s)))
expectEqual("ab", String(validatingCString: bindAsCChar(s)))
dealloc()
}
do {
let (s, dealloc) = getNonASCIIUTF8()
expectEqual("аб", String(validatingUTF8: bindAsCChar(s)))
expectEqual("аб", String(validatingCString: bindAsCChar(s)))
dealloc()
}
do {
let (s, dealloc) = getIllFormedUTF8String1()
expectNil(String(validatingUTF8: bindAsCChar(s)))
expectNil(String(validatingCString: bindAsCChar(s)))
dealloc()
}
}
@@ -324,14 +324,14 @@ CStringTests.test("String.cString.with.inout.CChar.conversion") {
expectUnreachable()
}
CStringTests.test("String.validatingUTF8.with.Array.input") {
CStringTests.test("String.validatingCString.with.Array.input") {
guard #available(SwiftStdlib 5.7, *) else { return }
do {
let (u8p, dealloc) = getASCIIUTF8()
defer { dealloc() }
let buffer = UnsafeBufferPointer(start: u8p, count: getUTF8Length(u8p)+1)
let str = buffer.withMemoryRebound(to: CChar.self) {
String(validatingUTF8: Array($0))
String(validatingCString: Array($0))
}
expectNotNil(str)
str?.withCString {
@@ -344,41 +344,41 @@ CStringTests.test("String.validatingUTF8.with.Array.input") {
// no need to test every case; that is covered in other tests
expectCrashLater(
// Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967)
// withMessage: "input of String.init(validatingUTF8:) must be null-terminated"
// withMessage: "input of String.init(validatingCString:) must be null-terminated"
)
_ = String(validatingUTF8: [])
_ = String(validatingCString: [])
expectUnreachable()
}
CStringTests.test("String.validatingUTF8.with.String.input") {
CStringTests.test("String.validatingCString.with.String.input") {
guard #available(SwiftStdlib 5.7, *) else { return }
let (u8p, dealloc) = getASCIIUTF8()
defer { dealloc() }
var str = String(validatingUTF8: "ab")
var str = String(validatingCString: "ab")
expectNotNil(str)
str?.withCString {
$0.withMemoryRebound(to: UInt8.self, capacity: getUTF8Length(u8p)+1) {
expectEqualCString(u8p, $0)
}
}
str = String(validatingUTF8: "")
str = String(validatingCString: "")
expectNotNil(str)
expectEqual(str?.isEmpty, true)
}
CStringTests.test("String.validatingUTF8.with.inout.conversion") {
CStringTests.test("String.validatingCString.with.inout.conversion") {
guard #available(SwiftStdlib 5.7, *) else { return }
var c = CChar.zero
var str = String(validatingUTF8: &c)
var str = String(validatingCString: &c)
expectNotNil(str)
expectEqual(str?.isEmpty, true)
c = 100
guard enableCrashTests else { return }
expectCrashLater(
// Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967)
// withMessage: "input of String.init(validatingUTF8:) must be null-terminated"
// withMessage: "input of String.init(validatingCString:) must be null-terminated"
)
str = String(validatingUTF8: &c)
str = String(validatingCString: &c)
expectUnreachable()
}

View File

@@ -6,7 +6,7 @@ func checkStringOverloadCompilationDiagnostics() {
_ = String(cString: "string") // expected-warning {{'init(cString:)' is deprecated: Use a copy of the String argument}}
_ = String(validatingUTF8: "string") // expected-warning {{init(validatingUTF8:)' is deprecated: Use a copy of the String argument}}
_ = String(validatingCString: "string") // expected-warning {{init(validatingCString:)' is deprecated: Use a copy of the String argument}}
_ = String.decodeCString("string", as: Unicode.UTF8.self) // expected-warning {{'decodeCString(_:as:repairingInvalidCodeUnits:)' is deprecated: Use a copy of the String argument}}
@@ -23,7 +23,7 @@ func checkInoutConversionOverloadCompilationDiagnostics() {
_ = String(cString: &c) // expected-warning {{'init(cString:)' is deprecated: Use String(_ scalar: Unicode.Scalar)}}
_ = String(validatingUTF8: &c) // expected-warning {{init(validatingUTF8:)' is deprecated: Use String(_ scalar: Unicode.Scalar)}}
_ = String(validatingCString: &c) // expected-warning {{init(validatingCString:)' is deprecated: Use String(_ scalar: Unicode.Scalar)}}
var u = Unicode.UTF8.CodeUnit.zero