@@ -108,22 +108,17 @@ CPPTRACE_BEGIN_NAMESPACE
108
108
}
109
109
110
110
std::string format (
111
- const stacktrace_frame& input_frame ,
111
+ const stacktrace_frame& frame ,
112
112
detail::optional<bool > color_override = detail::nullopt
113
113
) const {
114
114
std::ostringstream oss;
115
- detail::optional<stacktrace_frame> transformed_frame;
116
- if (options.transform ) {
117
- transformed_frame = options.transform (input_frame);
118
- }
119
- const stacktrace_frame& frame = options.transform ? transformed_frame.unwrap () : input_frame;
120
- print_frame_inner (oss, frame, color_override.value_or (options.color == color_mode::always));
115
+ print_internal (oss, frame, color_override.value_or (options.color == color_mode::always));
121
116
return std::move (oss).str ();
122
117
}
123
118
124
119
std::string format (const stacktrace& trace, detail::optional<bool > color_override = detail::nullopt) const {
125
120
std::ostringstream oss;
126
- print_internal (oss, trace, false , color_override);
121
+ print_internal (oss, trace, color_override. value_or (options. color == color_mode::always) );
127
122
return std::move (oss).str ();
128
123
}
129
124
@@ -135,14 +130,16 @@ CPPTRACE_BEGIN_NAMESPACE
135
130
const stacktrace_frame& frame,
136
131
detail::optional<bool > color_override = detail::nullopt
137
132
) const {
138
- print_frame_internal (stream, frame, color_override);
133
+ print_internal (stream, frame, color_override);
134
+ stream << " \n " ;
139
135
}
140
136
void print (
141
137
std::FILE* file,
142
138
const stacktrace_frame& frame,
143
139
detail::optional<bool > color_override = detail::nullopt
144
140
) const {
145
141
auto str = format (frame, color_override);
142
+ str += " \n " ;
146
143
std::fwrite (str.data (), 1 , str.size (), file);
147
144
}
148
145
@@ -154,18 +151,37 @@ CPPTRACE_BEGIN_NAMESPACE
154
151
const stacktrace& trace,
155
152
detail::optional<bool > color_override = detail::nullopt
156
153
) const {
157
- print_internal (stream, trace, true , color_override);
154
+ print_internal (stream, trace, color_override);
155
+ stream << " \n " ;
158
156
}
159
157
void print (
160
158
std::FILE* file,
161
159
const stacktrace& trace,
162
160
detail::optional<bool > color_override = detail::nullopt
163
161
) const {
164
162
auto str = format (trace, color_override);
163
+ str += " \n " ;
165
164
std::fwrite (str.data (), 1 , str.size (), file);
166
165
}
167
166
168
167
private:
168
+ struct color_setting {
169
+ bool color;
170
+ color_setting (bool color) : color(color) {}
171
+ detail::string_view reset () const {
172
+ return color ? RESET : " " ;
173
+ }
174
+ detail::string_view green () const {
175
+ return color ? GREEN : " " ;
176
+ }
177
+ detail::string_view yellow () const {
178
+ return color ? YELLOW : " " ;
179
+ }
180
+ detail::string_view blue () const {
181
+ return color ? BLUE : " " ;
182
+ }
183
+ };
184
+
169
185
bool stream_is_tty (std::ostream& stream) const {
170
186
// not great, but it'll have to do
171
187
return (&stream == &std::cout && isatty (stdout_fileno))
@@ -185,26 +201,36 @@ CPPTRACE_BEGIN_NAMESPACE
185
201
(!color_override || color_override.unwrap () != false ) &&
186
202
stream_is_tty (stream)
187
203
) {
188
- detail::enable_virtual_terminal_processing_if_needed ();
189
204
do_color = true ;
190
205
}
191
206
return do_color;
192
207
}
193
208
194
- void print_internal (std::ostream& stream, const stacktrace& trace, bool newline_at_end, detail::optional<bool > color_override) const {
195
- bool do_color = should_do_color (stream, color_override);
196
- maybe_ensure_virtual_terminal_processing (stream, do_color);
197
- print_internal (stream, trace, newline_at_end, do_color);
209
+ void print_internal (std::ostream& stream, const stacktrace_frame& input_frame, detail::optional<bool > color_override) const {
210
+ bool color = should_do_color (stream, color_override);
211
+ maybe_ensure_virtual_terminal_processing (stream, color);
212
+ detail::optional<stacktrace_frame> transformed_frame;
213
+ if (options.transform ) {
214
+ transformed_frame = options.transform (input_frame);
215
+ }
216
+ const stacktrace_frame& frame = options.transform ? transformed_frame.unwrap () : input_frame;
217
+ write_frame (stream, frame, color);
198
218
}
199
219
200
- void print_internal (std::ostream& stream, const stacktrace& trace, bool newline_at_end, bool color) const {
220
+ void print_internal (std::ostream& stream, const stacktrace& trace, detail::optional<bool > color_override) const {
221
+ bool color = should_do_color (stream, color_override);
222
+ maybe_ensure_virtual_terminal_processing (stream, color);
223
+ write_trace (stream, trace, color);
224
+ }
225
+
226
+ void write_trace (std::ostream& stream, const stacktrace& trace, bool color) const {
201
227
if (!options.header .empty ()) {
202
228
stream << options.header << ' \n ' ;
203
229
}
204
230
std::size_t counter = 0 ;
205
231
const auto & frames = trace.frames ;
206
232
if (frames.empty ()) {
207
- stream << " <empty trace>\n " ;
233
+ stream << " <empty trace>" ;
208
234
return ;
209
235
}
210
236
const auto frame_number_width = detail::n_digits (static_cast <int >(frames.size ()) - 1 );
@@ -214,14 +240,16 @@ CPPTRACE_BEGIN_NAMESPACE
214
240
transformed_frame = options.transform (frames[i]);
215
241
}
216
242
const stacktrace_frame& frame = options.transform ? transformed_frame.unwrap () : frames[i];
217
- if (options.filter && !options.filter (frame)) {
218
- if (!options.show_filtered_frames ) {
219
- counter++;
220
- continue ;
221
- }
222
- print_placeholder_frame (stream, frame_number_width, counter);
243
+ bool filter_out_frame = options.filter && !options.filter (frame);
244
+ if (filter_out_frame && !options.show_filtered_frames ) {
245
+ counter++;
246
+ continue ;
247
+ }
248
+ microfmt::print (stream, " #{<{}} " , frame_number_width, counter);
249
+ if (filter_out_frame) {
250
+ microfmt::print (stream, " (filtered)" );
223
251
} else {
224
- print_frame_internal (stream, frame, color, frame_number_width, counter );
252
+ write_frame (stream, frame, color);
225
253
if (frame.line .has_value () && !frame.filename .empty () && options.snippets ) {
226
254
auto snippet = detail::get_snippet (
227
255
frame.filename ,
@@ -235,83 +263,71 @@ CPPTRACE_BEGIN_NAMESPACE
235
263
}
236
264
}
237
265
}
238
- if (newline_at_end || i + 1 != frames.size ()) {
266
+ if (i + 1 != frames.size ()) {
239
267
stream << ' \n ' ;
240
268
}
241
269
counter++;
242
270
}
243
271
}
244
272
245
- void print_frame_internal (
246
- std::ostream& stream,
247
- const stacktrace_frame& frame,
248
- bool color,
249
- unsigned frame_number_width,
250
- std::size_t counter
251
- ) const {
252
- microfmt::print (stream, " #{<{}} " , frame_number_width, counter);
253
- print_frame_inner (stream, frame, color);
254
- }
255
-
256
- void print_placeholder_frame (std::ostream& stream, unsigned frame_number_width, std::size_t counter) const {
257
- microfmt::print (stream, " #{<{}} (filtered)" , frame_number_width, counter);
258
- }
259
-
260
- void print_frame_internal (
261
- std::ostream& stream,
262
- const stacktrace_frame& frame,
263
- detail::optional<bool > color_override
264
- ) const {
265
- bool do_color = should_do_color (stream, color_override);
266
- maybe_ensure_virtual_terminal_processing (stream, do_color);
267
- print_frame_inner (stream, frame, do_color);
273
+ void write_frame (std::ostream& stream, const stacktrace_frame& frame, color_setting color) const {
274
+ write_address (stream, frame, color);
275
+ if (frame.is_inline || options.addresses != address_mode::none) {
276
+ stream << ' ' ;
277
+ }
278
+ if (!frame.symbol .empty ()) {
279
+ write_symbol (stream, frame, color);
280
+ }
281
+ if (!frame.symbol .empty () && !frame.filename .empty ()) {
282
+ stream << ' ' ;
283
+ }
284
+ if (!frame.filename .empty ()) {
285
+ write_source_location (stream, frame, color);
286
+ }
268
287
}
269
288
270
- void print_frame_inner (std::ostream& stream, const stacktrace_frame& frame, bool color) const {
271
- const auto reset = color ? RESET : " " ;
272
- const auto green = color ? GREEN : " " ;
273
- const auto yellow = color ? YELLOW : " " ;
274
- const auto blue = color ? BLUE : " " ;
289
+ void write_address (std::ostream& stream, const stacktrace_frame& frame, color_setting color) const {
275
290
if (frame.is_inline ) {
276
- microfmt::print (stream, " {<{}} " , 2 * sizeof (frame_ptr) + 2 , " (inlined)" );
291
+ microfmt::print (stream, " {<{}}" , 2 * sizeof (frame_ptr) + 2 , " (inlined)" );
277
292
} else if (options.addresses != address_mode::none) {
278
293
auto address = options.addresses == address_mode::raw ? frame.raw_address : frame.object_address ;
279
- microfmt::print (stream, " {}0x{>{}:0h}{} " , blue, 2 * sizeof (frame_ptr), address, reset);
294
+ microfmt::print (stream, " {}0x{>{}:0h}{}" , color. blue () , 2 * sizeof (frame_ptr), address, color. reset () );
280
295
}
281
- if (!frame. symbol . empty ()) {
282
- detail::optional<std::string> maybe_stored_string;
283
- detail::string_view symbol;
284
- switch (options. symbols ) {
285
- case symbol_mode::full:
286
- symbol = frame. symbol ;
287
- break ;
288
- case symbol_mode::pruned:
289
- maybe_stored_string = prune_symbol (frame. symbol ) ;
290
- symbol = maybe_stored_string. unwrap ();
291
- break ;
292
- case symbol_mode::pretty:
293
- maybe_stored_string = prettify_symbol (frame. symbol ) ;
294
- symbol = maybe_stored_string. unwrap ();
295
- break ;
296
- default :
297
- PANIC ( " Unhandled symbol mode " ) ;
298
- }
299
- microfmt::print (stream, " in {}{}{} " , yellow, symbol, reset );
296
+ }
297
+
298
+ void write_symbol (std::ostream& stream, const stacktrace_frame& frame, color_setting color) const {
299
+ detail::optional<std::string> maybe_stored_string;
300
+ detail::string_view symbol;
301
+ switch (options. symbols ) {
302
+ case symbol_mode::full:
303
+ symbol = frame. symbol ;
304
+ break ;
305
+ case symbol_mode::pruned:
306
+ maybe_stored_string = prune_symbol (frame. symbol ) ;
307
+ symbol = maybe_stored_string. unwrap ();
308
+ break ;
309
+ case symbol_mode::pretty:
310
+ maybe_stored_string = prettify_symbol (frame. symbol ) ;
311
+ symbol = maybe_stored_string. unwrap ();
312
+ break ;
313
+ default :
314
+ PANIC ( " Unhandled symbol mode " );
300
315
}
301
- if (!frame.filename .empty ()) {
302
- microfmt::print (
303
- stream,
304
- " {}at {}{}{}" ,
305
- frame.symbol .empty () ? " " : " " ,
306
- green,
307
- options.paths == path_mode::full ? frame.filename : detail::basename (frame.filename , true ),
308
- reset
309
- );
310
- if (frame.line .has_value ()) {
311
- microfmt::print (stream, " :{}{}{}" , blue, frame.line .value (), reset);
312
- if (frame.column .has_value () && options.columns ) {
313
- microfmt::print (stream, " :{}{}{}" , blue, frame.column .value (), reset);
314
- }
316
+ microfmt::print (stream, " in {}{}{}" , color.yellow (), symbol, color.reset ());
317
+ }
318
+
319
+ void write_source_location (std::ostream& stream, const stacktrace_frame& frame, color_setting color) const {
320
+ microfmt::print (
321
+ stream,
322
+ " at {}{}{}" ,
323
+ color.green (),
324
+ options.paths == path_mode::full ? frame.filename : detail::basename (frame.filename , true ),
325
+ color.reset ()
326
+ );
327
+ if (frame.line .has_value ()) {
328
+ microfmt::print (stream, " :{}{}{}" , color.blue (), frame.line .value (), color.reset ());
329
+ if (frame.column .has_value () && options.columns ) {
330
+ microfmt::print (stream, " :{}{}{}" , color.blue (), frame.column .value (), color.reset ());
315
331
}
316
332
}
317
333
}
0 commit comments