@@ -692,29 +692,51 @@ extension Unicode.Scalar.Properties {
692692 /// all current case mappings. In the event more space is needed, it will be
693693 /// allocated on the heap.
694694 internal func _applyMapping( _ u_strTo: _U_StrToX ) -> String {
695- // TODO(String performance): Stack buffer first and then detect real count
696- let count = 64
697- var array = Array < UInt16 > ( repeating: 0 , count: count)
698- let len : Int = array. withUnsafeMutableBufferPointer { bufPtr in
695+ // Allocate 16 code units on the stack.
696+ var fixedArray = _FixedArray16 < UInt16 > ( allZeros: ( ) )
697+ let count : Int = fixedArray. withUnsafeMutableBufferPointer { buf in
699698 return _scalar. withUTF16CodeUnits { utf16 in
700699 var err = __swift_stdlib_U_ZERO_ERROR
701700 let correctSize = u_strTo (
702- bufPtr . baseAddress. _unsafelyUnwrappedUnchecked,
703- Int32 ( bufPtr . count) ,
701+ buf . baseAddress. _unsafelyUnwrappedUnchecked,
702+ Int32 ( buf . count) ,
704703 utf16. baseAddress. _unsafelyUnwrappedUnchecked,
705704 Int32 ( utf16. count) ,
706705 " " ,
707706 & err)
708707 guard err. isSuccess else {
709708 fatalError ( " Unexpected error case-converting Unicode scalar. " )
710709 }
711- // TODO: _internalInvariant(count == correctSize, "inconsistent ICU behavior")
712710 return Int ( correctSize)
713711 }
714712 }
715- // TODO: replace `len` with `count`
716- return array [ ..< len] . withUnsafeBufferPointer {
717- return String . _uncheckedFromUTF16 ( $0)
713+ if _fastPath ( count <= 16 ) {
714+ fixedArray. count = count
715+ return fixedArray. withUnsafeBufferPointer {
716+ String . _uncheckedFromUTF16 ( $0)
717+ }
718+ }
719+ // Allocate `count` code units on the heap.
720+ let array = Array < UInt16 > ( unsafeUninitializedCapacity: count) {
721+ buf, initializedCount in
722+ _scalar. withUTF16CodeUnits { utf16 in
723+ var err = __swift_stdlib_U_ZERO_ERROR
724+ let correctSize = u_strTo (
725+ buf. baseAddress. _unsafelyUnwrappedUnchecked,
726+ Int32 ( buf. count) ,
727+ utf16. baseAddress. _unsafelyUnwrappedUnchecked,
728+ Int32 ( utf16. count) ,
729+ " " ,
730+ & err)
731+ guard err. isSuccess else {
732+ fatalError ( " Unexpected error case-converting Unicode scalar. " )
733+ }
734+ _internalInvariant ( count == correctSize, " inconsistent ICU behavior " )
735+ initializedCount = count
736+ }
737+ }
738+ return array. withUnsafeBufferPointer {
739+ String . _uncheckedFromUTF16 ( $0)
718740 }
719741 }
720742
0 commit comments