@@ -44,7 +44,9 @@ extension String {
44
44
///
45
45
/// - Parameter cString: A pointer to a null-terminated UTF-8 code sequence.
46
46
public init ( cString: UnsafePointer < CChar > ) {
47
- self = _decodeValidCString ( cString, repair: true )
47
+ let len = UTF8 . _nullCodeUnitOffset ( in: cString)
48
+ self = String . _fromUTF8Repairing (
49
+ UnsafeBufferPointer ( start: cString. _asUInt8, count: len) ) . 0
48
50
}
49
51
50
52
/// Creates a new string by copying the null-terminated UTF-8 data referenced
@@ -53,7 +55,9 @@ extension String {
53
55
/// This is identical to init(cString: UnsafePointer<CChar> but operates on an
54
56
/// unsigned sequence of bytes.
55
57
public init ( cString: UnsafePointer < UInt8 > ) {
56
- self = _decodeValidCString ( cString, repair: true )
58
+ let len = UTF8 . _nullCodeUnitOffset ( in: cString)
59
+ self = String . _fromUTF8Repairing (
60
+ UnsafeBufferPointer ( start: cString, count: len) ) . 0
57
61
}
58
62
59
63
/// Creates a new string by copying and validating the null-terminated UTF-8
@@ -83,9 +87,11 @@ extension String {
83
87
///
84
88
/// - Parameter cString: A pointer to a null-terminated UTF-8 code sequence.
85
89
public init ? ( validatingUTF8 cString: UnsafePointer < CChar > ) {
86
- guard let str = _decodeCString ( cString, repair: false ) else {
87
- return nil
88
- }
90
+ let len = UTF8 . _nullCodeUnitOffset ( in: cString)
91
+ guard let str = String . _tryFromUTF8 (
92
+ UnsafeBufferPointer ( start: cString. _asUInt8, count: len) )
93
+ else { return nil }
94
+
89
95
self = str
90
96
}
91
97
@@ -133,92 +139,50 @@ extension String {
133
139
/// ill-formed sequence is detected, this method returns `nil`.
134
140
@_specialize ( where Encoding == Unicode. UTF8 )
135
141
@_specialize ( where Encoding == Unicode. UTF16 )
142
+ @inlinable // Fold away specializations
136
143
public static func decodeCString< Encoding : _UnicodeEncoding > (
137
144
_ cString: UnsafePointer < Encoding . CodeUnit > ? ,
138
145
as encoding: Encoding . Type ,
139
- repairingInvalidCodeUnits isRepairing: Bool = true )
140
- -> ( result: String , repairsMade: Bool ) ? {
141
-
142
- guard let cString = cString else {
143
- return nil
146
+ repairingInvalidCodeUnits isRepairing: Bool = true
147
+ ) -> ( result: String , repairsMade: Bool ) ? {
148
+ guard let cPtr = cString else { return nil }
149
+
150
+ if _fastPath ( encoding == Unicode . UTF8. self) {
151
+ let ptr = UnsafeRawPointer ( cPtr) . assumingMemoryBound ( to: UInt8 . self)
152
+ let len = UTF8 . _nullCodeUnitOffset ( in: ptr)
153
+ let codeUnits = UnsafeBufferPointer ( start: ptr, count: len)
154
+ if isRepairing {
155
+ return String . _fromUTF8Repairing ( codeUnits)
156
+ } else {
157
+ guard let str = String . _tryFromUTF8 ( codeUnits) else { return nil }
158
+ return ( str, false )
159
+ }
144
160
}
145
- var end = cString
146
- while end. pointee != 0 { end += 1 }
147
- let len = end - cString
148
- return _decodeCString (
149
- cString, as: encoding, length: len,
150
- repairingInvalidCodeUnits: isRepairing)
151
- }
152
-
153
- }
154
161
155
- /// From a non-`nil` `UnsafePointer` to a null-terminated string
156
- /// with possibly-transient lifetime, create a null-terminated array of 'C' char.
157
- /// Returns `nil` if passed a null pointer.
158
- public func _persistCString( _ p: UnsafePointer < CChar > ? ) -> [ CChar ] ? {
159
- guard let s = p else {
160
- return nil
161
- }
162
- let count = Int ( _swift_stdlib_strlen ( s) )
163
- var result = [ CChar] ( repeating: 0 , count: count + 1 )
164
- for i in 0 ..< count {
165
- result [ i] = s [ i]
166
- }
167
- return result
168
- }
169
-
170
- internal func _decodeValidCString(
171
- _ cString: UnsafePointer < Int8 > , repair: Bool
172
- ) -> String {
173
- let len = UTF8 . _nullCodeUnitOffset ( in: cString)
174
- return cString. withMemoryRebound ( to: UInt8 . self, capacity: len) {
175
- ( ptr: UnsafePointer < UInt8 > ) -> String in
176
- let bufPtr = UnsafeBufferPointer ( start: ptr, count: len)
177
- return String . _fromWellFormedUTF8 ( bufPtr, repair: repair)
162
+ var end = cPtr
163
+ while end. pointee != 0 { end += 1 }
164
+ let len = end - cPtr
165
+ let codeUnits = UnsafeBufferPointer ( start: cPtr, count: len)
166
+ return String . _fromCodeUnits (
167
+ codeUnits, encoding: encoding, repair: isRepairing)
178
168
}
179
- }
180
-
181
- internal func _decodeValidCString(
182
- _ cString: UnsafePointer < UInt8 > , repair: Bool
183
- ) -> String {
184
- let len = UTF8 . _nullCodeUnitOffset ( in: cString)
185
- let bufPtr = UnsafeBufferPointer ( start: cString, count: len)
186
- return String . _fromWellFormedUTF8 ( bufPtr, repair: repair)
187
- }
188
-
189
- internal func _decodeCString(
190
- _ cString: UnsafePointer < Int8 > , repair: Bool
191
- ) -> String ? {
192
- let len = UTF8 . _nullCodeUnitOffset ( in: cString)
193
- return cString. withMemoryRebound ( to: UInt8 . self, capacity: len) {
194
- ( ptr: UnsafePointer < UInt8 > ) -> String ? in
195
- let bufPtr = UnsafeBufferPointer ( start: ptr, count: len)
196
- return String . _fromUTF8 ( bufPtr, repair: repair)
169
+ /// Creates a string from the null-terminated sequence of bytes at the given
170
+ /// pointer.
171
+ ///
172
+ /// - Parameters:
173
+ /// - nullTerminatedCodeUnits: A pointer to a sequence of contiguous code
174
+ /// units in the encoding specified in `sourceEncoding`, ending just
175
+ /// before the first zero code unit.
176
+ /// - sourceEncoding: The encoding in which the code units should be
177
+ /// interpreted.
178
+ @_specialize ( where Encoding == Unicode. UTF8 )
179
+ @_specialize ( where Encoding == Unicode. UTF16 )
180
+ @inlinable // Fold away specializations
181
+ public init < Encoding: Unicode . Encoding > (
182
+ decodingCString ptr: UnsafePointer < Encoding . CodeUnit > ,
183
+ as sourceEncoding: Encoding . Type
184
+ ) {
185
+ self = String . decodeCString ( ptr, as: sourceEncoding) !. 0
197
186
}
198
187
}
199
188
200
- internal func _decodeCString(
201
- _ cString: UnsafePointer < UInt8 > , repair: Bool
202
- ) -> String ? {
203
- let len = UTF8 . _nullCodeUnitOffset ( in: cString)
204
- let bufPtr = UnsafeBufferPointer ( start: cString, count: len)
205
- return String . _fromUTF8 ( bufPtr, repair: repair)
206
- }
207
-
208
- /// Creates a new string by copying the null-terminated data referenced by
209
- /// the given pointer using the specified encoding.
210
- ///
211
- /// This internal helper takes the string length as an argument.
212
- internal func _decodeCString< Encoding : _UnicodeEncoding > (
213
- _ cString: UnsafePointer < Encoding . CodeUnit > ,
214
- as encoding: Encoding . Type , length: Int ,
215
- repairingInvalidCodeUnits isRepairing: Bool = true )
216
- -> ( result: String , repairsMade: Bool ) ? {
217
-
218
- let buffer = UnsafeBufferPointer < Encoding . CodeUnit > (
219
- start: cString, count: length)
220
-
221
- let ( guts, hadError) = _StringGuts. fromCodeUnits (
222
- buffer, encoding: encoding, repairIllFormedSequences: isRepairing)
223
- return guts. map { ( result: String ( $0) , repairsMade: hadError) }
224
- }
0 commit comments