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

View File

@ -130,7 +130,7 @@ namespace detail {
snippet += YELLOW;
}
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) {
snippet += RESET;
}

View File

@ -289,12 +289,15 @@ namespace addr2line {
}
std::string address_input;
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
address_input += '\n';
'\n'
#else
address_input += ' ';
' '
#endif
);
}
auto output = split(trim(resolve_addresses(address_input, object_name)), "\n");
VERIFY(output.size() == entries_vec.size());

View File

@ -6,6 +6,7 @@
#include <algorithm>
#include <array>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
@ -320,6 +321,12 @@ namespace microfmt {
void print(std::ostream& ostream, const S& fmt, Args&&... 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

View File

@ -107,12 +107,6 @@ namespace detail {
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() {
std::uint16_t num = 0x1;
const auto* ptr = (std::uint8_t*)&num;