Skip to content

Commit 50b83c8

Browse files
authored
Merge pull request #68423 from glessard/se0405-take2
[se-0405] rename `String.init(validatingUTF8:)`
2 parents d8c809c + b67b2cb commit 50b83c8

File tree

11 files changed

+98
-40
lines changed

11 files changed

+98
-40
lines changed

stdlib/private/StdlibUnittest/InspectValue.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public enum SwiftRuntime {
1616
private static func _metadataKind<T>(of value: T) -> UnsafePointer<CChar>
1717

1818
public static func metadataKind<T>(of value: T) -> String {
19-
return String(validatingUTF8: _metadataKind(of: value))!
19+
return String(validatingCString: _metadataKind(of: value))!
2020
}
2121
}
2222

stdlib/private/StdlibUnittest/StdlibUnittest.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ func _printDebuggingAdvice(_ fullTestName: String) {
850850
#else
851851
let interpreter = getenv("SWIFT_INTERPRETER")
852852
if interpreter != nil {
853-
if let interpreterCmd = String(validatingUTF8: interpreter!) {
853+
if let interpreterCmd = String(validatingCString: interpreter!) {
854854
invocation.insert(interpreterCmd, at: 0)
855855
}
856856
}

stdlib/private/SwiftPrivateLibcExtras/Subprocess.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ public func spawnChild(_ args: [String])
405405
childArgs.insert(CommandLine.arguments[0], at: 0)
406406
let interpreter = getenv("SWIFT_INTERPRETER")
407407
if interpreter != nil {
408-
if let invocation = String(validatingUTF8: interpreter!) {
408+
if let invocation = String(validatingCString: interpreter!) {
409409
childArgs.insert(invocation, at: 0)
410410
}
411411
}

stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ internal func getAddressInfoForImage(atIndex i: UInt32) ->
6464
debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") }
6565
let header = unsafeBitCast(_dyld_get_image_header(i),
6666
to: UnsafePointer<MachHeader>.self)
67-
let name = String(validatingUTF8: _dyld_get_image_name(i)!)!
67+
let name = String(validatingCString: _dyld_get_image_name(i)!)!
6868
var size: UInt = 0
6969
let address = getsegmentdata(header, "__TEXT", &size)
7070
return (name, address, size)
@@ -111,7 +111,7 @@ internal func getReflectionInfoForImage(atIndex i: UInt32) -> ReflectionInfo? {
111111
let capture = getSectionInfo("__swift5_capture", header)
112112
let typeref = getSectionInfo("__swift5_typeref", header)
113113
let reflstr = getSectionInfo("__swift5_reflstr", header)
114-
return ReflectionInfo(imageName: String(validatingUTF8: imageName)!,
114+
return ReflectionInfo(imageName: String(validatingCString: imageName)!,
115115
fieldmd: fieldmd,
116116
assocty: assocty,
117117
builtin: builtin,
@@ -160,7 +160,7 @@ internal func getReflectionInfoForImage(atIndex i: UInt32) -> ReflectionInfo? {
160160
return _getMetadataSection(UInt(i)).map { rawPointer in
161161
let name = _getMetadataSectionName(rawPointer)
162162
let metadataSection = rawPointer.bindMemory(to: MetadataSections.self, capacity: 1).pointee
163-
return ReflectionInfo(imageName: String(validatingUTF8: name)!,
163+
return ReflectionInfo(imageName: String(validatingCString: name)!,
164164
fieldmd: Section(range: metadataSection.swift5_fieldmd),
165165
assocty: Section(range: metadataSection.swift5_assocty),
166166
builtin: Section(range: metadataSection.swift5_builtin),
@@ -302,7 +302,7 @@ internal func sendReflectionInfos() {
302302
internal func printErrnoAndExit() {
303303
debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") }
304304
let errorCString = strerror(errno)!
305-
let message = String(validatingUTF8: errorCString)! + "\n"
305+
let message = String(validatingCString: errorCString)! + "\n"
306306
let bytes = Array(message.utf8)
307307
fwrite(bytes, 1, bytes.count, stderr)
308308
fflush(stderr)

stdlib/public/Backtracing/Backtrace.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ public struct Backtrace: CustomStringConvertible, Sendable {
435435
_dyld_process_info_for_each_segment(dyldInfo, machHeaderAddress) {
436436
address, size, name in
437437

438-
if let name = String(validatingUTF8: name!), name == "__TEXT" {
438+
if let name = String(validatingCString: name!), name == "__TEXT" {
439439
endOfText = address + size
440440
}
441441
}

stdlib/public/core/CString.swift

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,40 @@ extension String {
124124
self = ""
125125
}
126126

127+
/// Creates a new string by copying and validating the null-terminated UTF-8
128+
/// data referenced by the given pointer.
129+
///
130+
/// This initializer does not try to repair ill-formed UTF-8 code unit
131+
/// sequences. If any are found, the result of the initializer is `nil`.
132+
///
133+
/// The following example calls this initializer with pointers to the
134+
/// contents of two different `CChar` arrays---the first with well-formed
135+
/// UTF-8 code unit sequences and the second with an ill-formed sequence at
136+
/// the end.
137+
///
138+
/// let validUTF8: [CChar] = [67, 97, 102, -61, -87, 0]
139+
/// validUTF8.withUnsafeBufferPointer { ptr in
140+
/// let s = String(validatingCString: ptr.baseAddress!)
141+
/// print(s)
142+
/// }
143+
/// // Prints "Optional("Café")"
144+
///
145+
/// let invalidUTF8: [CChar] = [67, 97, 102, -61, 0]
146+
/// invalidUTF8.withUnsafeBufferPointer { ptr in
147+
/// let s = String(validatingCString: ptr.baseAddress!)
148+
/// print(s)
149+
/// }
150+
/// // Prints "nil"
151+
///
152+
/// - Parameter nullTerminatedUTF8:
153+
/// A pointer to a null-terminated UTF-8 code sequence.
154+
@inlinable
155+
@_alwaysEmitIntoClient
156+
public init?(validatingCString nullTerminatedUTF8: UnsafePointer<CChar>) {
157+
// FIXME: https://github.com/apple/swift/issues/68433 (rdar://115296219)
158+
self.init(validatingUTF8: nullTerminatedUTF8)
159+
}
160+
127161
/// Creates a new string by copying and validating the null-terminated UTF-8
128162
/// data referenced by the given pointer.
129163
///
@@ -149,7 +183,11 @@ extension String {
149183
/// }
150184
/// // Prints "nil"
151185
///
186+
/// Note: This initializer is deprecated. Use
187+
/// `String.init?(validatingCString:)` instead.
188+
///
152189
/// - Parameter cString: A pointer to a null-terminated UTF-8 code sequence.
190+
@available(swift, deprecated: 6, renamed: "String.init(validatingCString:)")
153191
public init?(validatingUTF8 cString: UnsafePointer<CChar>) {
154192
let len = UTF8._nullCodeUnitOffset(in: cString)
155193
guard let str = cString.withMemoryRebound(to: UInt8.self, capacity: len, {
@@ -162,39 +200,59 @@ extension String {
162200

163201
@inlinable
164202
@_alwaysEmitIntoClient
165-
public init?(validatingUTF8 cString: [CChar]) {
166-
guard let length = cString.firstIndex(of: 0) else {
203+
public init?(validatingCString nullTerminatedUTF8: [CChar]) {
204+
guard let length = nullTerminatedUTF8.firstIndex(of: 0) else {
167205
_preconditionFailure(
168-
"input of String.init(validatingUTF8:) must be null-terminated"
206+
"input of String.init(validatingCString:) must be null-terminated"
169207
)
170208
}
171-
guard let string = cString.prefix(length).withUnsafeBufferPointer({
209+
let string = nullTerminatedUTF8.prefix(length).withUnsafeBufferPointer {
172210
$0.withMemoryRebound(to: UInt8.self, String._tryFromUTF8(_:))
173-
})
174-
else { return nil }
175-
211+
}
212+
guard let string else { return nil }
176213
self = string
177214
}
178215

216+
@inlinable
217+
@_alwaysEmitIntoClient
218+
@available(*, deprecated, renamed: "String.init(validatingCString:)")
219+
public init?(validatingUTF8 cString: [CChar]) {
220+
self.init(validatingCString: cString)
221+
}
222+
223+
@inlinable
224+
@_alwaysEmitIntoClient
225+
@available(*, deprecated, message: "Use a copy of the String argument")
226+
public init?(validatingCString nullTerminatedUTF8: String) {
227+
self = nullTerminatedUTF8.withCString(String.init(cString:))
228+
}
229+
179230
@inlinable
180231
@_alwaysEmitIntoClient
181232
@available(*, deprecated, message: "Use a copy of the String argument")
182233
public init?(validatingUTF8 cString: String) {
183-
self = cString.withCString(String.init(cString:))
234+
self.init(validatingCString: cString)
184235
}
185236

186237
@inlinable
187238
@_alwaysEmitIntoClient
188239
@available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)")
189-
public init?(validatingUTF8 cString: inout CChar) {
190-
guard cString == 0 else {
240+
public init?(validatingCString nullTerminatedUTF8: inout CChar) {
241+
guard nullTerminatedUTF8 == 0 else {
191242
_preconditionFailure(
192243
"input of String.init(validatingUTF8:) must be null-terminated"
193244
)
194245
}
195246
self = ""
196247
}
197248

249+
@inlinable
250+
@_alwaysEmitIntoClient
251+
@available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)")
252+
public init?(validatingUTF8 cString: inout CChar) {
253+
self.init(validatingCString: &cString)
254+
}
255+
198256
/// Creates a new string by copying the null-terminated data referenced by
199257
/// the given pointer using the specified encoding.
200258
///

stdlib/public/core/KeyPath.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ public class AnyKeyPath: Hashable, _AppendKeyPath {
196196
}
197197
guard let ptr = _kvcKeyPathStringPtr else { return nil }
198198

199-
return String(validatingUTF8: ptr)
199+
return String(validatingCString: ptr)
200200
}
201201
}
202202

stdlib/public/core/OutputStream.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ internal func _adHocPrint_unlocked<T, TargetStream: TextOutputStream>(
355355
target.write(")")
356356
case .enum:
357357
if let cString = _getEnumCaseName(value),
358-
let caseName = String(validatingUTF8: cString) {
358+
let caseName = String(validatingCString: cString) {
359359
// Write the qualified type name in debugPrint.
360360
if isDebugPrint {
361361
printTypeName(mirror.subjectType)
@@ -390,7 +390,7 @@ internal func _adHocPrint_unlocked<T, TargetStream: TextOutputStream>(
390390
} else {
391391
// Fall back to the type or an opaque summary of the kind
392392
if let cString = _opaqueSummary(mirror.subjectType),
393-
let opaqueSummary = String(validatingUTF8: cString) {
393+
let opaqueSummary = String(validatingCString: cString) {
394394
target.write(opaqueSummary)
395395
} else {
396396
target.write(_typeName(mirror.subjectType, qualified: true))
@@ -532,7 +532,7 @@ internal func _dumpPrint_unlocked<T, TargetStream: TextOutputStream>(
532532
case .`enum`:
533533
target.write(_typeName(mirror.subjectType, qualified: true))
534534
if let cString = _getEnumCaseName(value),
535-
let caseName = String(validatingUTF8: cString) {
535+
let caseName = String(validatingCString: cString) {
536536
target.write(".")
537537
target.write(caseName)
538538
}

stdlib/public/core/ReflectionMirror.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ internal func getChild<T>(of value: T, type: Any.Type, index: Int) -> (label: St
6666

6767
let value = _getChild(of: value, type: type, index: index, outName: &nameC, outFreeFunc: &freeFunc)
6868

69-
let name = nameC.flatMap({ String(validatingUTF8: $0) })
69+
let name = nameC.flatMap({ String(validatingCString: $0) })
7070
freeFunc?(nameC)
7171
return (name, value)
7272
}

test/stdlib/StringAPICString.swift

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -107,20 +107,20 @@ func expectEqualCString(_ lhs: UnsafePointer<UInt8>,
107107
}
108108
}
109109

110-
CStringTests.test("String.init(validatingUTF8:)") {
110+
CStringTests.test("String.init(validatingCString:)") {
111111
do {
112112
let (s, dealloc) = getASCIIUTF8()
113-
expectEqual("ab", String(validatingUTF8: bindAsCChar(s)))
113+
expectEqual("ab", String(validatingCString: bindAsCChar(s)))
114114
dealloc()
115115
}
116116
do {
117117
let (s, dealloc) = getNonASCIIUTF8()
118-
expectEqual("аб", String(validatingUTF8: bindAsCChar(s)))
118+
expectEqual("аб", String(validatingCString: bindAsCChar(s)))
119119
dealloc()
120120
}
121121
do {
122122
let (s, dealloc) = getIllFormedUTF8String1()
123-
expectNil(String(validatingUTF8: bindAsCChar(s)))
123+
expectNil(String(validatingCString: bindAsCChar(s)))
124124
dealloc()
125125
}
126126
}
@@ -324,14 +324,14 @@ CStringTests.test("String.cString.with.inout.CChar.conversion") {
324324
expectUnreachable()
325325
}
326326

327-
CStringTests.test("String.validatingUTF8.with.Array.input") {
327+
CStringTests.test("String.validatingCString.with.Array.input") {
328328
guard #available(SwiftStdlib 5.7, *) else { return }
329329
do {
330330
let (u8p, dealloc) = getASCIIUTF8()
331331
defer { dealloc() }
332332
let buffer = UnsafeBufferPointer(start: u8p, count: getUTF8Length(u8p)+1)
333333
let str = buffer.withMemoryRebound(to: CChar.self) {
334-
String(validatingUTF8: Array($0))
334+
String(validatingCString: Array($0))
335335
}
336336
expectNotNil(str)
337337
str?.withCString {
@@ -344,41 +344,41 @@ CStringTests.test("String.validatingUTF8.with.Array.input") {
344344
// no need to test every case; that is covered in other tests
345345
expectCrashLater(
346346
// Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967)
347-
// withMessage: "input of String.init(validatingUTF8:) must be null-terminated"
347+
// withMessage: "input of String.init(validatingCString:) must be null-terminated"
348348
)
349-
_ = String(validatingUTF8: [])
349+
_ = String(validatingCString: [])
350350
expectUnreachable()
351351
}
352352

353-
CStringTests.test("String.validatingUTF8.with.String.input") {
353+
CStringTests.test("String.validatingCString.with.String.input") {
354354
guard #available(SwiftStdlib 5.7, *) else { return }
355355
let (u8p, dealloc) = getASCIIUTF8()
356356
defer { dealloc() }
357-
var str = String(validatingUTF8: "ab")
357+
var str = String(validatingCString: "ab")
358358
expectNotNil(str)
359359
str?.withCString {
360360
$0.withMemoryRebound(to: UInt8.self, capacity: getUTF8Length(u8p)+1) {
361361
expectEqualCString(u8p, $0)
362362
}
363363
}
364-
str = String(validatingUTF8: "")
364+
str = String(validatingCString: "")
365365
expectNotNil(str)
366366
expectEqual(str?.isEmpty, true)
367367
}
368368

369-
CStringTests.test("String.validatingUTF8.with.inout.conversion") {
369+
CStringTests.test("String.validatingCString.with.inout.conversion") {
370370
guard #available(SwiftStdlib 5.7, *) else { return }
371371
var c = CChar.zero
372-
var str = String(validatingUTF8: &c)
372+
var str = String(validatingCString: &c)
373373
expectNotNil(str)
374374
expectEqual(str?.isEmpty, true)
375375
c = 100
376376
guard enableCrashTests else { return }
377377
expectCrashLater(
378378
// Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967)
379-
// withMessage: "input of String.init(validatingUTF8:) must be null-terminated"
379+
// withMessage: "input of String.init(validatingCString:) must be null-terminated"
380380
)
381-
str = String(validatingUTF8: &c)
381+
str = String(validatingCString: &c)
382382
expectUnreachable()
383383
}
384384

0 commit comments

Comments
 (0)