@@ -674,20 +674,45 @@ private extension swiftscan_functions_t {
674674 }
675675}
676676
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)
690688 }
691- for ptr in cstrings { if let ptr = ptr { free ( ptr) } }
692689 return result
693690}
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