@@ -42,22 +42,84 @@ extension String {
42
42
/// }
43
43
/// // Prints "Caf�"
44
44
///
45
- /// - Parameter cString : A pointer to a null-terminated UTF-8 code sequence.
46
- public init ( cString: UnsafePointer < CChar > ) {
47
- let len = UTF8 . _nullCodeUnitOffset ( in: cString )
45
+ /// - Parameter nullTerminatedUTF8 : A pointer to a null-terminated UTF-8 code sequence.
46
+ public init ( cString nullTerminatedUTF8 : UnsafePointer < CChar > ) {
47
+ let len = UTF8 . _nullCodeUnitOffset ( in: nullTerminatedUTF8 )
48
48
self = String . _fromUTF8Repairing (
49
- UnsafeBufferPointer ( start: cString. _asUInt8, count: len) ) . 0
49
+ UnsafeBufferPointer ( start: nullTerminatedUTF8. _asUInt8, count: len) ) . 0
50
+ }
51
+
52
+ @inlinable
53
+ @_alwaysEmitIntoClient
54
+ public init ( cString nullTerminatedUTF8: [ CChar ] ) {
55
+ self = nullTerminatedUTF8. withUnsafeBytes {
56
+ String ( _checkingCString: $0. assumingMemoryBound ( to: UInt8 . self) )
57
+ }
58
+ }
59
+
60
+ @_alwaysEmitIntoClient
61
+ private init ( _checkingCString bytes: UnsafeBufferPointer < UInt8 > ) {
62
+ guard let length = bytes. firstIndex ( of: 0 ) else {
63
+ _preconditionFailure (
64
+ " input of String.init(cString:) must be null-terminated "
65
+ )
66
+ }
67
+ self = String . _fromUTF8Repairing (
68
+ UnsafeBufferPointer (
69
+ start: bytes. baseAddress. _unsafelyUnwrappedUnchecked,
70
+ count: length
71
+ )
72
+ ) . 0
73
+ }
74
+
75
+ @inlinable
76
+ @_alwaysEmitIntoClient
77
+ @available ( * , deprecated, message: " Use String(_ scalar: Unicode.Scalar) " )
78
+ public init ( cString nullTerminatedUTF8: inout CChar ) {
79
+ guard nullTerminatedUTF8 == 0 else {
80
+ _preconditionFailure (
81
+ " input of String.init(cString:) must be null-terminated "
82
+ )
83
+ }
84
+ self = " "
50
85
}
51
86
52
87
/// Creates a new string by copying the null-terminated UTF-8 data referenced
53
88
/// by the given pointer.
54
89
///
55
90
/// This is identical to `init(cString: UnsafePointer<CChar>)` but operates on
56
91
/// an unsigned sequence of bytes.
57
- public init ( cString: UnsafePointer < UInt8 > ) {
58
- let len = UTF8 . _nullCodeUnitOffset ( in: cString )
92
+ public init ( cString nullTerminatedUTF8 : UnsafePointer < UInt8 > ) {
93
+ let len = UTF8 . _nullCodeUnitOffset ( in: nullTerminatedUTF8 )
59
94
self = String . _fromUTF8Repairing (
60
- UnsafeBufferPointer ( start: cString, count: len) ) . 0
95
+ UnsafeBufferPointer ( start: nullTerminatedUTF8, count: len) ) . 0
96
+ }
97
+
98
+ @inlinable
99
+ @_alwaysEmitIntoClient
100
+ public init ( cString nullTerminatedUTF8: [ UInt8 ] ) {
101
+ self = nullTerminatedUTF8. withUnsafeBufferPointer {
102
+ String ( _checkingCString: $0)
103
+ }
104
+ }
105
+
106
+ @inlinable
107
+ @_alwaysEmitIntoClient
108
+ @available ( * , deprecated, message: " Use a copy of the String argument " )
109
+ public init ( cString nullTerminatedUTF8: String ) {
110
+ self = nullTerminatedUTF8. withCString ( String . init ( cString: ) )
111
+ }
112
+
113
+ @inlinable
114
+ @_alwaysEmitIntoClient
115
+ @available ( * , deprecated, message: " Use String(_ scalar: Unicode.Scalar) " )
116
+ public init ( cString nullTerminatedUTF8: inout UInt8 ) {
117
+ guard nullTerminatedUTF8 == 0 else {
118
+ _preconditionFailure (
119
+ " input of String.init(cString:) must be null-terminated "
120
+ )
121
+ }
122
+ self = " "
61
123
}
62
124
63
125
/// Creates a new string by copying and validating the null-terminated UTF-8
@@ -95,6 +157,40 @@ extension String {
95
157
self = str
96
158
}
97
159
160
+ @inlinable
161
+ @_alwaysEmitIntoClient
162
+ public init ? ( validatingUTF8 cString: [ CChar ] ) {
163
+ guard let length = cString. firstIndex ( of: 0 ) else {
164
+ _preconditionFailure (
165
+ " input of String.init(validatingUTF8:) must be null-terminated "
166
+ )
167
+ }
168
+ guard let string = cString. prefix ( length) . withUnsafeBytes ( {
169
+ String . _tryFromUTF8 ( $0. assumingMemoryBound ( to: UInt8 . self) )
170
+ } ) else { return nil }
171
+
172
+ self = string
173
+ }
174
+
175
+ @inlinable
176
+ @_alwaysEmitIntoClient
177
+ @available ( * , deprecated, message: " Use a copy of the String argument " )
178
+ public init ? ( validatingUTF8 cString: String ) {
179
+ self = cString. withCString ( String . init ( cString: ) )
180
+ }
181
+
182
+ @inlinable
183
+ @_alwaysEmitIntoClient
184
+ @available ( * , deprecated, message: " Use String(_ scalar: Unicode.Scalar) " )
185
+ public init ? ( validatingUTF8 cString: inout CChar ) {
186
+ guard cString == 0 else {
187
+ _preconditionFailure (
188
+ " input of String.init(validatingUTF8:) must be null-terminated "
189
+ )
190
+ }
191
+ self = " "
192
+ }
193
+
98
194
/// Creates a new string by copying the null-terminated data referenced by
99
195
/// the given pointer using the specified encoding.
100
196
///
@@ -166,6 +262,77 @@ extension String {
166
262
return String . _fromCodeUnits (
167
263
codeUnits, encoding: encoding, repair: isRepairing)
168
264
}
265
+
266
+ @_specialize ( where Encoding == Unicode. UTF8 )
267
+ @_specialize ( where Encoding == Unicode. UTF16 )
268
+ @inlinable // Fold away specializations
269
+ @_alwaysEmitIntoClient
270
+ public static func decodeCString< Encoding: _UnicodeEncoding > (
271
+ _ cString: [ Encoding . CodeUnit ] ,
272
+ as encoding: Encoding . Type ,
273
+ repairingInvalidCodeUnits isRepairing: Bool = true
274
+ ) -> ( result: String , repairsMade: Bool ) ? {
275
+ guard let length = cString. firstIndex ( of: 0 ) else {
276
+ _preconditionFailure (
277
+ " input of decodeCString(_:as:repairingInvalidCodeUnits:) must be null-terminated "
278
+ )
279
+ }
280
+
281
+ if _fastPath ( encoding == Unicode . UTF8. self) {
282
+ return cString. prefix ( length) . withUnsafeBytes {
283
+ buf -> ( result: String , repairsMade: Bool ) ? in
284
+ let codeUnits = buf. assumingMemoryBound ( to: UInt8 . self)
285
+ if isRepairing {
286
+ return String . _fromUTF8Repairing ( codeUnits)
287
+ }
288
+ else if let str = String . _tryFromUTF8 ( codeUnits) {
289
+ return ( str, false )
290
+ }
291
+ return nil
292
+ }
293
+ }
294
+
295
+ return cString. prefix ( length) . withUnsafeBufferPointer {
296
+ buf -> ( result: String , repairsMade: Bool ) ? in
297
+ String . _fromCodeUnits ( buf, encoding: encoding, repair: isRepairing)
298
+ }
299
+ }
300
+
301
+ @_specialize ( where Encoding == Unicode. UTF8 )
302
+ @_specialize ( where Encoding == Unicode. UTF16 )
303
+ @inlinable
304
+ @_alwaysEmitIntoClient
305
+ @available ( * , deprecated, message: " Use a copy of the String argument " )
306
+ public static func decodeCString< Encoding: _UnicodeEncoding > (
307
+ _ cString: String ,
308
+ as encoding: Encoding . Type ,
309
+ repairingInvalidCodeUnits isRepairing: Bool = true
310
+ ) -> ( result: String , repairsMade: Bool ) ? {
311
+ return cString. withCString ( encodedAs: encoding) {
312
+ String . decodeCString (
313
+ $0, as: encoding, repairingInvalidCodeUnits: isRepairing
314
+ )
315
+ }
316
+ }
317
+
318
+ @_specialize ( where Encoding == Unicode. UTF8 )
319
+ @_specialize ( where Encoding == Unicode. UTF16 )
320
+ @inlinable
321
+ @_alwaysEmitIntoClient
322
+ @available ( * , deprecated, message: " Use String(_ scalar: Unicode.Scalar) " )
323
+ public static func decodeCString< Encoding: _UnicodeEncoding > (
324
+ _ cString: inout Encoding . CodeUnit ,
325
+ as encoding: Encoding . Type ,
326
+ repairingInvalidCodeUnits isRepairing: Bool = true
327
+ ) -> ( result: String , repairsMade: Bool ) ? {
328
+ guard cString == 0 else {
329
+ _preconditionFailure (
330
+ " input of decodeCString(_:as:repairingInvalidCodeUnits:) must be null-terminated "
331
+ )
332
+ }
333
+ return ( " " , false )
334
+ }
335
+
169
336
/// Creates a string from the null-terminated sequence of bytes at the given
170
337
/// pointer.
171
338
///
@@ -179,10 +346,52 @@ extension String {
179
346
@_specialize ( where Encoding == Unicode. UTF16 )
180
347
@inlinable // Fold away specializations
181
348
public init < Encoding: Unicode . Encoding > (
182
- decodingCString ptr : UnsafePointer < Encoding . CodeUnit > ,
349
+ decodingCString nullTerminatedCodeUnits : UnsafePointer < Encoding . CodeUnit > ,
183
350
as sourceEncoding: Encoding . Type
184
351
) {
185
- self = String . decodeCString ( ptr, as: sourceEncoding) !. 0
352
+ self = String . decodeCString ( nullTerminatedCodeUnits, as: sourceEncoding) !. 0
353
+ }
354
+
355
+ @_specialize ( where Encoding == Unicode. UTF8 )
356
+ @_specialize ( where Encoding == Unicode. UTF16 )
357
+ @inlinable // Fold away specializations
358
+ @_alwaysEmitIntoClient
359
+ public init < Encoding: Unicode . Encoding > (
360
+ decodingCString nullTerminatedCodeUnits: [ Encoding . CodeUnit ] ,
361
+ as sourceEncoding: Encoding . Type
362
+ ) {
363
+ self = String . decodeCString ( nullTerminatedCodeUnits, as: sourceEncoding) !. 0
364
+ }
365
+
366
+ @_specialize ( where Encoding == Unicode. UTF8 )
367
+ @_specialize ( where Encoding == Unicode. UTF16 )
368
+ @inlinable
369
+ @_alwaysEmitIntoClient
370
+ @available ( * , deprecated, message: " Use a copy of the String argument " )
371
+ public init < Encoding: _UnicodeEncoding > (
372
+ decodingCString nullTerminatedCodeUnits: String ,
373
+ as sourceEncoding: Encoding . Type
374
+ ) {
375
+ self = nullTerminatedCodeUnits. withCString ( encodedAs: sourceEncoding) {
376
+ String ( decodingCString: $0, as: sourceEncoding. self)
377
+ }
378
+ }
379
+
380
+ @_specialize ( where Encoding == Unicode. UTF8 )
381
+ @_specialize ( where Encoding == Unicode. UTF16 )
382
+ @inlinable // Fold away specializations
383
+ @_alwaysEmitIntoClient
384
+ @available ( * , deprecated, message: " Use String(_ scalar: Unicode.Scalar) " )
385
+ public init < Encoding: Unicode . Encoding > (
386
+ decodingCString nullTerminatedCodeUnits: inout Encoding . CodeUnit ,
387
+ as sourceEncoding: Encoding . Type
388
+ ) {
389
+ guard nullTerminatedCodeUnits == 0 else {
390
+ _preconditionFailure (
391
+ " input of String.init(decodingCString:as:) must be null-terminated "
392
+ )
393
+ }
394
+ self = " "
186
395
}
187
396
}
188
397
0 commit comments