Replace most stream use with new formatting system

This commit is contained in:
Jeremy 2024-03-30 20:25:06 -05:00
parent acaa4f42e6
commit ab63c34827
No known key found for this signature in database
GPG Key ID: 19AA8270105E8EB4
5 changed files with 59 additions and 98 deletions

View File

@ -4,8 +4,7 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstdio> #include <cstdio>
#include <iomanip> #include <cstring>
#include <iostream>
#include <new> #include <new>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
@ -105,39 +104,29 @@ namespace cpptrace {
} }
std::string stacktrace_frame::to_string() const { std::string stacktrace_frame::to_string() const {
std::ostringstream oss; std::string str;
oss << *this; if(is_inline) {
return std::move(oss).str(); str += microfmt::format("{<{}}", 2 * sizeof(frame_ptr) + 2, "(inlined)");
} } else {
str += microfmt::format("0x{<{}:0h}", 2 * sizeof(frame_ptr), raw_address);
std::ostream& operator<<(std::ostream& stream, const stacktrace_frame& frame) {
stream
<< std::hex
<< "0x"
<< std::setw(2 * sizeof(frame_ptr))
<< std::setfill('0')
<< frame.raw_address
<< std::dec
<< std::setfill(' ');
if(!frame.symbol.empty()) {
stream
<< " in "
<< frame.symbol;
} }
if(!frame.filename.empty()) { if(!symbol.empty()) {
stream str += microfmt::format(" in {}", symbol);
<< " at " }
<< frame.filename; if(!filename.empty()) {
if(frame.line.has_value()) { str += microfmt::format(" at {}", filename);
stream if(line.has_value()) {
<< ":" str += microfmt::format(":{}", line.value());
<< frame.line.value(); if(column.has_value()) {
if(frame.column.has_value()) { str += microfmt::format(":{}", column.value());
stream << frame.column.value();
} }
} }
} }
return stream; return str;
}
std::ostream& operator<<(std::ostream& stream, const stacktrace_frame& frame) {
return stream << frame.to_string();
} }
CPPTRACE_FORCE_NO_INLINE CPPTRACE_FORCE_NO_INLINE
@ -173,56 +162,25 @@ namespace cpptrace {
const auto green = color ? GREEN : ""; const auto green = color ? GREEN : "";
const auto yellow = color ? YELLOW : ""; const auto yellow = color ? YELLOW : "";
const auto blue = color ? BLUE : ""; const auto blue = color ? BLUE : "";
stream std::string line = microfmt::format("#{<{}} ", frame_number_width, counter);
<< '#'
<< std::setw(static_cast<int>(frame_number_width))
<< std::left
<< counter
<< std::right
<< " ";
if(frame.is_inline) { if(frame.is_inline) {
stream line += microfmt::format("{<{}}", 2 * sizeof(frame_ptr) + 2, "(inlined)");
<< std::setw(2 * sizeof(frame_ptr) + 2)
<< "(inlined)";
} else { } else {
stream line += microfmt::format("{}0x{<{}:0h}{}", blue, 2 * sizeof(frame_ptr), frame.raw_address, reset);
<< std::hex
<< blue
<< "0x"
<< std::setw(2 * sizeof(frame_ptr))
<< std::setfill('0')
<< frame.raw_address
<< std::dec
<< std::setfill(' ')
<< reset;
} }
if(!frame.symbol.empty()) { if(!frame.symbol.empty()) {
stream line += microfmt::format(" in {}{}{}", yellow, frame.symbol, reset);
<< " in "
<< yellow
<< frame.symbol
<< reset;
} }
if(!frame.filename.empty()) { if(!frame.filename.empty()) {
stream line += microfmt::format(" at {}{}{}", green, frame.filename, reset);
<< " at "
<< green
<< frame.filename
<< reset;
if(frame.line.has_value()) { if(frame.line.has_value()) {
stream line += microfmt::format(":{}{}{}", blue, frame.line.value(), reset);
<< ":"
<< blue
<< frame.line.value()
<< reset;
if(frame.column.has_value()) { if(frame.column.has_value()) {
stream << ':' line += microfmt::format(":{}{}{}", blue, frame.column.value(), reset);
<< blue
<< std::to_string(frame.column.value())
<< reset;
} }
} }
} }
stream << line;
} }
void stacktrace::print(std::ostream& stream, bool color, bool newline_at_end, const char* header) const { void stacktrace::print(std::ostream& stream, bool color, bool newline_at_end, const char* header) const {
@ -233,10 +191,10 @@ namespace cpptrace {
) { ) {
detail::enable_virtual_terminal_processing_if_needed(); detail::enable_virtual_terminal_processing_if_needed();
} }
stream<<(header ? header : "Stack trace (most recent call first):") << '\n'; stream << (header ? header : "Stack trace (most recent call first):") << '\n';
std::size_t counter = 0; std::size_t counter = 0;
if(frames.empty()) { if(frames.empty()) {
stream<<"<empty trace>" << '\n'; stream << "<empty trace>\n";
return; return;
} }
const auto frame_number_width = detail::n_digits(static_cast<int>(frames.size()) - 1); const auto frame_number_width = detail::n_digits(static_cast<int>(frames.size()) - 1);
@ -269,10 +227,10 @@ namespace cpptrace {
) { ) {
detail::enable_virtual_terminal_processing_if_needed(); detail::enable_virtual_terminal_processing_if_needed();
} }
stream<<(header ? header : "Stack trace (most recent call first):") << '\n'; stream << (header ? header : "Stack trace (most recent call first):") << '\n';
std::size_t counter = 0; std::size_t counter = 0;
if(frames.empty()) { if(frames.empty()) {
stream<<"<empty trace>" << '\n'; stream << "<empty trace>" << '\n';
return; return;
} }
const auto frame_number_width = detail::n_digits(static_cast<int>(frames.size()) - 1); const auto frame_number_width = detail::n_digits(static_cast<int>(frames.size()) - 1);
@ -433,29 +391,28 @@ namespace cpptrace {
try { try {
auto ptr = std::current_exception(); auto ptr = std::current_exception();
if(ptr == nullptr) { if(ptr == nullptr) {
std::cerr << "terminate called without an active exception\n"; fputs("terminate called without an active exception", stderr);
print_terminate_trace(); print_terminate_trace();
} else { } else {
std::rethrow_exception(ptr); std::rethrow_exception(ptr);
} }
} catch(cpptrace::exception& e) { } catch(cpptrace::exception& e) {
std::cerr << "Terminate called after throwing an instance of " microfmt::print(
<< demangle(typeid(e).name()) stderr,
<< ": " "Terminate called after throwing an instance of {}: {}\n",
<< e.message() demangle(typeid(e).name()),
<< '\n'; e.message()
);
e.trace().print(std::cerr, isatty(stderr_fileno)); e.trace().print(std::cerr, isatty(stderr_fileno));
} catch(std::exception& e) { } catch(std::exception& e) {
std::cerr << "Terminate called after throwing an instance of " microfmt::print(
<< demangle(typeid(e).name()) stderr, "Terminate called after throwing an instance of {}: {}\n", demangle(typeid(e).name()), e.what()
<< ": " );
<< e.what()
<< '\n';
print_terminate_trace(); print_terminate_trace();
} catch(...) { } catch(...) {
std::cerr << "Terminate called after throwing an instance of " microfmt::print(
<< detail::exception_type_name() stderr, "Terminate called after throwing an instance of {}\n", detail::exception_type_name()
<< "\n"; );
print_terminate_trace(); print_terminate_trace();
} }
std::flush(std::cerr); std::flush(std::cerr);

View File

@ -130,7 +130,7 @@ namespace detail {
snippet += YELLOW; snippet += YELLOW;
} }
auto line_str = std::to_string(line); auto line_str = std::to_string(line);
snippet += std::string(margin_width - std::min(line_str.size(), margin_width), ' ') + line_str + ": "; snippet += microfmt::format("{>{}}: ", margin_width, line_str);
if(color && line == target_line) { if(color && line == target_line) {
snippet += RESET; snippet += RESET;
} }

View File

@ -289,12 +289,15 @@ namespace addr2line {
} }
std::string address_input; std::string address_input;
for(const auto& pair : entries_vec) { for(const auto& pair : entries_vec) {
address_input += to_hex(pair.first.get().object_address); address_input += microfmt::format(
"{:h}{}",
pair.first.get().object_address,
#if !IS_WINDOWS #if !IS_WINDOWS
address_input += '\n'; '\n'
#else #else
address_input += ' '; ' '
#endif #endif
);
} }
auto output = split(trim(resolve_addresses(address_input, object_name)), "\n"); auto output = split(trim(resolve_addresses(address_input, object_name)), "\n");
VERIFY(output.size() == entries_vec.size()); VERIFY(output.size() == entries_vec.size());

View File

@ -6,6 +6,7 @@
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <cstdint> #include <cstdint>
#include <cstdio>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <string> #include <string>
@ -320,6 +321,12 @@ namespace microfmt {
void print(std::ostream& ostream, const S& fmt, Args&&... args) { void print(std::ostream& ostream, const S& fmt, Args&&... args) {
ostream<<format(fmt, args...); ostream<<format(fmt, args...);
} }
template<typename S, typename... Args>
void print(std::FILE* stream, const S& fmt, Args&&... args) {
auto str = format(fmt, args...);
fwrite(str.data(), 1, str.size(), stream);
}
} }
#endif #endif

View File

@ -107,12 +107,6 @@ namespace detail {
return str.substr(left, right - left); return str.substr(left, right - left);
} }
inline std::string to_hex(std::uintptr_t addr) {
std::stringstream sstream;
sstream<<std::hex<<addr;
return std::move(sstream).str();
}
inline bool is_little_endian() { inline bool is_little_endian() {
std::uint16_t num = 0x1; std::uint16_t num = 0x1;
const auto* ptr = (std::uint8_t*)&num; const auto* ptr = (std::uint8_t*)&num;