@@ -674,20 +674,45 @@ private extension swiftscan_functions_t {
674
674
}
675
675
}
676
676
677
- // TODO: Move to TSC?
678
- /// Perform an `action` passing it a `const char **` constructed out of `[String]`
679
- @_spi ( Testing) public func withArrayOfCStrings< T> ( _ strings: [ String ] ,
680
- _ action: ( UnsafeMutablePointer < UnsafePointer < Int8 > ? > ? ) -> T ) -> T
681
- {
682
- #if os(Windows)
683
- let cstrings = strings. map { _strdup ( $0) } + [ nil ]
684
- #else
685
- let cstrings = strings. map { strdup ( $0) } + [ nil ]
686
- #endif
687
- let unsafeCStrings = cstrings. map { UnsafePointer ( $0) }
688
- let result = unsafeCStrings. withUnsafeBufferPointer {
689
- action ( UnsafeMutablePointer ( mutating: $0. baseAddress) )
677
+ // TODO: Move the following functions to TSC?
678
+ /// Helper function to scan a sequence type to help generate pointers for C String Arrays.
679
+ func scan<
680
+ S: Sequence , U
681
+ > ( _ seq: S , _ initial: U , _ combine: ( U , S . Element ) -> U ) -> [ U ] {
682
+ var result : [ U ] = [ ]
683
+ result. reserveCapacity ( seq. underestimatedCount)
684
+ var runningResult = initial
685
+ for element in seq {
686
+ runningResult = combine ( runningResult, element)
687
+ result. append ( runningResult)
690
688
}
691
- for ptr in cstrings { if let ptr = ptr { free ( ptr) } }
692
689
return result
693
690
}
691
+
692
+ /// Perform an `action` passing it a `const char **` constructed out of `[String]`
693
+ @_spi ( Testing) public func withArrayOfCStrings< T> (
694
+ _ args: [ String ] ,
695
+ _ body: ( UnsafeMutablePointer < UnsafePointer < Int8 > ? > ? ) -> T
696
+ ) -> T {
697
+ let argsCounts = Array ( args. map { $0. utf8. count + 1 } )
698
+ let argsOffsets = [ 0 ] + scan( argsCounts, 0 , + )
699
+ let argsBufferSize = argsOffsets. last!
700
+ var argsBuffer : [ UInt8 ] = [ ]
701
+ argsBuffer. reserveCapacity ( argsBufferSize)
702
+ for arg in args {
703
+ argsBuffer. append ( contentsOf: arg. utf8)
704
+ argsBuffer. append ( 0 )
705
+ }
706
+ return argsBuffer. withUnsafeMutableBufferPointer {
707
+ ( argsBuffer) in
708
+ let ptr = UnsafeRawPointer ( argsBuffer. baseAddress!) . bindMemory (
709
+ to: Int8 . self, capacity: argsBuffer. count)
710
+ var cStrings : [ UnsafePointer < Int8 > ? ] = argsOffsets. map { ptr + $0 }
711
+ cStrings [ cStrings. count - 1 ] = nil
712
+ return cStrings. withUnsafeMutableBufferPointer {
713
+ let unsafeString = UnsafeMutableRawPointer ( $0. baseAddress!) . bindMemory (
714
+ to: UnsafePointer< Int8>? . self , capacity: $0. count)
715
+ return body ( unsafeString)
716
+ }
717
+ }
718
+ }
0 commit comments