@@ -160,32 +160,19 @@ internal func _createRegexForPattern(_ pattern: String, _ options: NSRegularExpr
160
160
return regex
161
161
}
162
162
163
- internal func _bytesInEncoding( _ str: NSString , _ encoding: String . Encoding , _ fatalOnError: Bool , _ externalRep: Bool , _ lossy: Bool ) -> UnsafePointer < Int8 > ? {
164
- let theRange = NSRange ( location: 0 , length: str. length)
163
+ // Caller must free, or leak, the pointer
164
+ fileprivate func _allocateBytesInEncoding( _ str: NSString , _ encoding: String . Encoding ) -> UnsafeMutableBufferPointer < Int8 > ? {
165
+ let theRange : NSRange = NSRange ( location: 0 , length: str. length)
165
166
var cLength = 0
166
- var used = 0
167
- var options : NSString . EncodingConversionOptions = [ ]
168
- if externalRep {
169
- options. formUnion ( . externalRepresentation)
170
- }
171
- if lossy {
172
- options. formUnion ( . allowLossy)
173
- }
174
- if !str. getBytes ( nil , maxLength: Int . max - 1 , usedLength: & cLength, encoding: encoding. rawValue, options: options, range: theRange, remaining: nil ) {
175
- if fatalOnError {
176
- fatalError ( " Conversion on encoding failed " )
177
- }
167
+ if !str. getBytes ( nil , maxLength: Int . max - 1 , usedLength: & cLength, encoding: encoding. rawValue, options: [ ] , range: theRange, remaining: nil ) {
178
168
return nil
179
169
}
180
170
181
- let buffer = malloc ( cLength + 1 ) !. bindMemory ( to: Int8 . self, capacity: cLength + 1 )
182
- if !str. getBytes ( buffer, maxLength: cLength, usedLength: & used, encoding: encoding. rawValue, options: options, range: theRange, remaining: nil ) {
183
- fatalError ( " Internal inconsistency; previously claimed getBytes returned success but failed with similar invocation " )
184
- }
171
+ let buffer = UnsafeMutableBufferPointer< Int8> . allocate( capacity: cLength + 1 )
172
+ buffer. initialize ( repeating: 0 )
173
+ _ = str. getBytes ( buffer. baseAddress, maxLength: cLength, usedLength: nil , encoding: encoding. rawValue, options: [ ] , range: theRange, remaining: nil )
185
174
186
- buffer. advanced ( by: cLength) . initialize ( to: 0 )
187
-
188
- return UnsafePointer ( buffer) // leaked and should be autoreleased via a NSData backing but we cannot here
175
+ return buffer
189
176
}
190
177
191
178
internal func isALineSeparatorTypeCharacter( _ ch: unichar ) -> Bool {
@@ -903,8 +890,13 @@ extension NSString {
903
890
}
904
891
}
905
892
893
+ @available ( * , deprecated, message: " On platforms without Objective-C autorelease pools, use withCString instead " )
906
894
public var utf8String : UnsafePointer < Int8 > ? {
907
- return _bytesInEncoding ( self , . utf8, false , false , false )
895
+ guard let buffer = _allocateBytesInEncoding ( self , . utf8) else {
896
+ return nil
897
+ }
898
+ // leaked. On Darwin, freed via an autorelease
899
+ return UnsafePointer < Int8 > ( buffer. baseAddress)
908
900
}
909
901
910
902
public var fastestEncoding : UInt {
@@ -961,8 +953,24 @@ extension NSString {
961
953
0 , nil , 0 , nil ) == length
962
954
}
963
955
964
- public func cString( using encoding: UInt ) -> UnsafePointer < Int8 > ? {
965
- return _bytesInEncoding ( self , String . Encoding ( rawValue: encoding) , false , false , false )
956
+ @available ( * , deprecated, message: " On platforms without Objective-C autorelease pools, use withCString(encodedAs:_) instead " )
957
+ public func cString( using encoding: UInt ) -> UnsafePointer < Int8 > ? {
958
+ // leaked. On Darwin, freed via an autorelease
959
+ guard let buffer = _allocateBytesInEncoding ( self , String . Encoding ( rawValue: encoding) ) else {
960
+ return nil
961
+ }
962
+ // leaked. On Darwin, freed via an autorelease
963
+ return UnsafePointer < Int8 > ( buffer. baseAddress)
964
+ }
965
+
966
+ internal func _withCString< T> ( using encoding: UInt , closure: ( UnsafePointer < Int8 > ? ) -> T ) -> T {
967
+ let buffer = _allocateBytesInEncoding ( self , String . Encoding ( rawValue: encoding) )
968
+ let result = closure ( buffer? . baseAddress)
969
+ if let buffer {
970
+ buffer. deinitialize ( )
971
+ buffer. deallocate ( )
972
+ }
973
+ return result
966
974
}
967
975
968
976
public func getCString( _ buffer: UnsafeMutablePointer < Int8 > , maxLength maxBufferCount: Int , encoding: UInt ) -> Bool {
0 commit comments