@@ -42,22 +42,84 @@ extension String {
4242 /// }
4343 /// // Prints "Caf�"
4444 ///
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 )
4848 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 = " "
5085 }
5186
5287 /// Creates a new string by copying the null-terminated UTF-8 data referenced
5388 /// by the given pointer.
5489 ///
5590 /// This is identical to `init(cString: UnsafePointer<CChar>)` but operates on
5691 /// 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 )
5994 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 = " "
61123 }
62124
63125 /// Creates a new string by copying and validating the null-terminated UTF-8
@@ -95,6 +157,40 @@ extension String {
95157 self = str
96158 }
97159
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+
98194 /// Creates a new string by copying the null-terminated data referenced by
99195 /// the given pointer using the specified encoding.
100196 ///
@@ -166,6 +262,77 @@ extension String {
166262 return String . _fromCodeUnits (
167263 codeUnits, encoding: encoding, repair: isRepairing)
168264 }
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+
169336 /// Creates a string from the null-terminated sequence of bytes at the given
170337 /// pointer.
171338 ///
@@ -179,10 +346,52 @@ extension String {
179346 @_specialize ( where Encoding == Unicode. UTF16 )
180347 @inlinable // Fold away specializations
181348 public init < Encoding: Unicode . Encoding > (
182- decodingCString ptr : UnsafePointer < Encoding . CodeUnit > ,
349+ decodingCString nullTerminatedCodeUnits : UnsafePointer < Encoding . CodeUnit > ,
183350 as sourceEncoding: Encoding . Type
184351 ) {
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 = " "
186395 }
187396}
188397
0 commit comments