@@ -55,6 +55,29 @@ private struct Metadata: Encodable {
5555 }
5656}
5757
58+ internal struct Output : TextOutputStream {
59+ let fileHandle : FileHandle
60+ init ( _ outputFile: String ? = nil ) throws {
61+ if let outputFile {
62+ if FileManager ( ) . createFile ( atPath: outputFile, contents: nil ) {
63+ self . fileHandle = try FileHandle ( forWritingAtPath: outputFile) !
64+ } else {
65+ print ( " Unable to create file \( outputFile) " )
66+ exit ( 1 )
67+ }
68+ } else {
69+ self . fileHandle = FileHandle . standardOutput
70+ }
71+ }
72+
73+ mutating func write( _ string: String ) {
74+ if let encodedString = string. data ( using: . utf8) {
75+ fileHandle. write ( encodedString)
76+ }
77+ }
78+
79+ }
80+
5881internal struct DumpGenericMetadata : ParsableCommand {
5982 static let configuration = CommandConfiguration (
6083 abstract: " Print the target's generic metadata allocations. " )
@@ -96,56 +119,58 @@ internal struct DumpGenericMetadata: ParsableCommand {
96119 backtrace: currentBacktrace)
97120 }
98121
99- if let outputFile = genericMetadataOptions. outputJson {
100- try dumpToJson ( process: process, generics: generics,
101- outputPath: outputFile)
122+ if genericMetadataOptions. json {
123+ try dumpJson ( process: process, generics: generics)
102124 } else {
103- try dumpToStdout ( process: process, generics: generics)
125+ try dumpText ( process: process, generics: generics)
104126 }
105127 }
106128 }
107129
108- private func dumpToStdout ( process: any RemoteProcess , generics: [ Metadata ] ) throws {
130+ private func dumpText ( process: any RemoteProcess , generics: [ Metadata ] ) throws {
109131 var errorneousMetadata : [ ( ptr: swift_reflection_ptr_t , name: String ) ] = [ ]
110-
111- print ( " Address " , " Allocation " , " Size " , " Offset " , " isArrayOfClass " , " Name " , separator: " \t " )
132+ var output = try Output ( genericMetadataOptions . outputFile )
133+ print ( " Address " , " Allocation " , " Size " , " Offset " , " isArrayOfClass " , " Name " , separator: " \t " , to : & output )
112134 generics. forEach {
113- print ( " \( hex: $0. ptr) " , terminator: " \t " )
135+ print ( " \( hex: $0. ptr) " , terminator: " \t " , to : & output )
114136 if let allocation = $0. allocation, let offset = $0. offset {
115- print ( " \( hex: allocation. ptr) \t \( allocation. size) \t \( offset) " , terminator: " \t " )
137+ print ( " \( hex: allocation. ptr) \t \( allocation. size) \t \( offset) " , terminator: " \t " , to : & output )
116138 } else {
117139 if $0. garbage {
118140 errorneousMetadata. append ( ( ptr: $0. ptr, name: $0. name) )
119141 }
120- print ( " ??? \t ?? \t ??? " , terminator: " \t " )
142+ print ( " ??? \t ?? \t ??? " , terminator: " \t " , to : & output )
121143 }
122- print ( $0. isArrayOfClass, terminator: " \t " )
123- print ( $0. name)
144+ print ( $0. isArrayOfClass, terminator: " \t " , to : & output )
145+ print ( $0. name, to : & output )
124146 if let _ = backtraceOptions. style, let _ = $0. allocation {
125- print ( $0. backtrace ?? " No stacktrace available " )
147+ print ( $0. backtrace ?? " No stacktrace available " , to : & output )
126148 }
127149 }
128150
129151 if errorneousMetadata. count > 0 {
130- print ( " Error: The following metadata was not found in any DATA or AUTH segments, may be garbage. " )
152+ print ( " Error: The following metadata was not found in any DATA or AUTH segments, may be garbage. " , to : & output )
131153 errorneousMetadata. forEach {
132- print ( " \( hex: $0. ptr) \t \( $0. name) " )
154+ print ( " \( hex: $0. ptr) \t \( $0. name) " , to : & output )
133155 }
134156 }
135157 }
136158
137- private func dumpToJson( process: any RemoteProcess ,
138- generics: [ Metadata ] ,
139- outputPath: String ) throws {
159+ private func dumpJson( process: any RemoteProcess ,
160+ generics: [ Metadata ] ) throws {
140161 struct AllMetadataEntries : Encodable {
141162 var metadata : [ Metadata ]
142163 }
143164 let allMetadataEntries = AllMetadataEntries ( metadata: generics)
144165 let encoder = JSONEncoder ( )
145166 encoder. outputFormatting = . prettyPrinted
146167 let data = try encoder. encode ( allMetadataEntries)
147- try String ( data: data, encoding: . utf8) !
148- . write ( toFile: outputPath, atomically: true , encoding: . utf8)
168+ let jsonOutput = String ( data: data, encoding: . utf8) !
169+ if let outputFile = genericMetadataOptions. outputFile {
170+ try jsonOutput. write ( toFile: outputFile, atomically: true , encoding: . utf8)
171+ } else {
172+ print ( jsonOutput)
173+ }
149174 }
150175
151176}
0 commit comments