@@ -167,8 +167,9 @@ internal func _cocoaStringSubscript(
167167}
168168
169169@_effects ( releasenone)
170- private func _NSStringCopyUTF8 (
170+ private func _NSStringCopyBytes (
171171 _ o: _StringSelectorHolder ,
172+ encoding: UInt ,
172173 into bufPtr: UnsafeMutableRawBufferPointer
173174) -> Int ? {
174175 let ptr = bufPtr. baseAddress. _unsafelyUnwrappedUnchecked
@@ -179,7 +180,7 @@ private func _NSStringCopyUTF8(
179180 ptr,
180181 maxLength: bufPtr. count,
181182 usedLength: & usedLen,
182- encoding: _cocoaUTF8Encoding ,
183+ encoding: encoding ,
183184 options: 0 ,
184185 range: _SwiftNSRange ( location: 0 , length: len) ,
185186 remaining: & remainingRange
@@ -195,7 +196,23 @@ internal func _cocoaStringCopyUTF8(
195196 _ target: _CocoaString ,
196197 into bufPtr: UnsafeMutableRawBufferPointer
197198) -> Int ? {
198- return _NSStringCopyUTF8 ( _objc ( target) , into: bufPtr)
199+ return _NSStringCopyBytes (
200+ _objc ( target) ,
201+ encoding: _cocoaUTF8Encoding,
202+ into: bufPtr
203+ )
204+ }
205+
206+ @_effects ( releasenone)
207+ internal func _cocoaStringCopyASCII(
208+ _ target: _CocoaString ,
209+ into bufPtr: UnsafeMutableRawBufferPointer
210+ ) -> Int ? {
211+ return _NSStringCopyBytes (
212+ _objc ( target) ,
213+ encoding: _cocoaASCIIEncoding,
214+ into: bufPtr
215+ )
199216}
200217
201218@_effects ( readonly)
@@ -346,17 +363,30 @@ internal func _bridgeTagged(
346363 _internalInvariant ( _isObjCTaggedPointer ( cocoa) )
347364 return _cocoaStringCopyUTF8 ( cocoa, into: bufPtr)
348365}
366+
367+ @_effects ( releasenone) // @opaque
368+ internal func _bridgeTaggedASCII(
369+ _ cocoa: _CocoaString ,
370+ intoUTF8 bufPtr: UnsafeMutableRawBufferPointer
371+ ) -> Int ? {
372+ _internalInvariant ( _isObjCTaggedPointer ( cocoa) )
373+ return _cocoaStringCopyASCII ( cocoa, into: bufPtr)
374+ }
349375#endif
350376
351377@_effects ( readonly)
352378private func _NSStringASCIIPointer( _ str: _StringSelectorHolder ) -> UnsafePointer < UInt8 > ? {
353- // TODO(String bridging): Is there a better interface here? Ideally we'd be
354- // able to ask for UTF8 rather than just ASCII
355379 //TODO(String bridging): Unconditionally asking for nul-terminated contents is
356380 // overly conservative and hurts perf with some NSStrings
357381 return str. _fastCStringContents ( 1 ) ? . _asUInt8
358382}
359383
384+ @_effects ( readonly)
385+ private func _NSStringUTF8Pointer( _ str: _StringSelectorHolder ) -> UnsafePointer < UInt8 > ? {
386+ //We don't have a way to ask for UTF8 here currently
387+ return _NSStringASCIIPointer ( str)
388+ }
389+
360390@_effects ( readonly) // @opaque
361391private func _withCocoaASCIIPointer< R> (
362392 _ str: _CocoaString ,
@@ -371,7 +401,7 @@ private func _withCocoaASCIIPointer<R>(
371401 if requireStableAddress {
372402 return nil // tagged pointer strings don't support _fastCStringContents
373403 }
374- if let smol = _SmallString ( taggedCocoa : str) {
404+ if let smol = _SmallString ( taggedASCIICocoa : str) {
375405 return _StringGuts ( smol) . withFastUTF8 {
376406 work ( $0. baseAddress. _unsafelyUnwrappedUnchecked)
377407 }
@@ -385,6 +415,34 @@ private func _withCocoaASCIIPointer<R>(
385415 return nil
386416}
387417
418+ @_effects ( readonly) // @opaque
419+ private func _withCocoaUTF8Pointer< R> (
420+ _ str: _CocoaString ,
421+ requireStableAddress: Bool ,
422+ work: ( UnsafePointer < UInt8 > ) -> R ?
423+ ) -> R ? {
424+ #if !(arch(i386) || arch(arm) || arch(arm64_32))
425+ if _isObjCTaggedPointer ( str) {
426+ if let ptr = getConstantTaggedCocoaContents ( str) ? . asciiContentsPointer {
427+ return work ( ptr)
428+ }
429+ if requireStableAddress {
430+ return nil // tagged pointer strings don't support _fastCStringContents
431+ }
432+ if let smol = _SmallString ( taggedCocoa: str) {
433+ return _StringGuts ( smol) . withFastUTF8 {
434+ work ( $0. baseAddress. _unsafelyUnwrappedUnchecked)
435+ }
436+ }
437+ }
438+ #endif
439+ defer { _fixLifetime ( str) }
440+ if let ptr = _NSStringUTF8Pointer ( _objc ( str) ) {
441+ return work ( ptr)
442+ }
443+ return nil
444+ }
445+
388446@_effects ( readonly) // @opaque
389447internal func withCocoaASCIIPointer< R> (
390448 _ str: _CocoaString ,
@@ -393,12 +451,26 @@ internal func withCocoaASCIIPointer<R>(
393451 return _withCocoaASCIIPointer ( str, requireStableAddress: false , work: work)
394452}
395453
454+ @_effects ( readonly) // @opaque
455+ internal func withCocoaUTF8Pointer< R> (
456+ _ str: _CocoaString ,
457+ work: ( UnsafePointer < UInt8 > ) -> R ?
458+ ) -> R ? {
459+ return _withCocoaUTF8Pointer ( str, requireStableAddress: false , work: work)
460+ }
461+
396462@_effects ( readonly)
397463internal func stableCocoaASCIIPointer( _ str: _CocoaString )
398464 -> UnsafePointer < UInt8 > ? {
399465 return _withCocoaASCIIPointer ( str, requireStableAddress: true , work: { $0 } )
400466}
401467
468+ @_effects ( readonly)
469+ internal func stableCocoaUTF8Pointer( _ str: _CocoaString )
470+ -> UnsafePointer < UInt8 > ? {
471+ return _withCocoaUTF8Pointer ( str, requireStableAddress: true , work: { $0 } )
472+ }
473+
402474private enum CocoaStringPointer {
403475 case ascii( UnsafePointer < UInt8 > )
404476 case utf8( UnsafePointer < UInt8 > )
0 commit comments