@@ -108,22 +108,17 @@ CPPTRACE_BEGIN_NAMESPACE
108108 }
109109
110110 std::string format (
111- const stacktrace_frame& input_frame ,
111+ const stacktrace_frame& frame ,
112112 detail::optional<bool > color_override = detail::nullopt
113113 ) const {
114114 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));
121116 return std::move (oss).str ();
122117 }
123118
124119 std::string format (const stacktrace& trace, detail::optional<bool > color_override = detail::nullopt ) const {
125120 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) );
127122 return std::move (oss).str ();
128123 }
129124
@@ -135,14 +130,16 @@ CPPTRACE_BEGIN_NAMESPACE
135130 const stacktrace_frame& frame,
136131 detail::optional<bool > color_override = detail::nullopt
137132 ) const {
138- print_frame_internal (stream, frame, color_override);
133+ print_internal (stream, frame, color_override);
134+ stream << " \n " ;
139135 }
140136 void print (
141137 std::FILE* file,
142138 const stacktrace_frame& frame,
143139 detail::optional<bool > color_override = detail::nullopt
144140 ) const {
145141 auto str = format (frame, color_override);
142+ str += " \n " ;
146143 std::fwrite (str.data (), 1 , str.size (), file);
147144 }
148145
@@ -154,18 +151,37 @@ CPPTRACE_BEGIN_NAMESPACE
154151 const stacktrace& trace,
155152 detail::optional<bool > color_override = detail::nullopt
156153 ) const {
157- print_internal (stream, trace, true , color_override);
154+ print_internal (stream, trace, color_override);
155+ stream << " \n " ;
158156 }
159157 void print (
160158 std::FILE* file,
161159 const stacktrace& trace,
162160 detail::optional<bool > color_override = detail::nullopt
163161 ) const {
164162 auto str = format (trace, color_override);
163+ str += " \n " ;
165164 std::fwrite (str.data (), 1 , str.size (), file);
166165 }
167166
168167 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+
169185 bool stream_is_tty (std::ostream& stream) const {
170186 // not great, but it'll have to do
171187 return (&stream == &std::cout && isatty (stdout_fileno))
@@ -185,26 +201,36 @@ CPPTRACE_BEGIN_NAMESPACE
185201 (!color_override || color_override.unwrap () != false ) &&
186202 stream_is_tty (stream)
187203 ) {
188- detail::enable_virtual_terminal_processing_if_needed ();
189204 do_color = true ;
190205 }
191206 return do_color;
192207 }
193208
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);
198218 }
199219
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 {
201227 if (!options.header .empty ()) {
202228 stream << options.header << ' \n ' ;
203229 }
204230 std::size_t counter = 0 ;
205231 const auto & frames = trace.frames ;
206232 if (frames.empty ()) {
207- stream << " <empty trace>\n " ;
233+ stream << " <empty trace>" ;
208234 return ;
209235 }
210236 const auto frame_number_width = detail::n_digits (static_cast <int >(frames.size ()) - 1 );
@@ -214,14 +240,16 @@ CPPTRACE_BEGIN_NAMESPACE
214240 transformed_frame = options.transform (frames[i]);
215241 }
216242 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)" );
223251 } else {
224- print_frame_internal (stream, frame, color, frame_number_width, counter );
252+ write_frame (stream, frame, color);
225253 if (frame.line .has_value () && !frame.filename .empty () && options.snippets ) {
226254 auto snippet = detail::get_snippet (
227255 frame.filename ,
@@ -235,83 +263,71 @@ CPPTRACE_BEGIN_NAMESPACE
235263 }
236264 }
237265 }
238- if (newline_at_end || i + 1 != frames.size ()) {
266+ if (i + 1 != frames.size ()) {
239267 stream << ' \n ' ;
240268 }
241269 counter++;
242270 }
243271 }
244272
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+ }
268287 }
269288
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 {
275290 if (frame.is_inline ) {
276- microfmt::print (stream, " {<{}} " , 2 * sizeof (frame_ptr) + 2 , " (inlined)" );
291+ microfmt::print (stream, " {<{}}" , 2 * sizeof (frame_ptr) + 2 , " (inlined)" );
277292 } else if (options.addresses != address_mode::none) {
278293 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 () );
280295 }
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 " );
300315 }
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 ());
315331 }
316332 }
317333 }
0 commit comments