Replace most stream use with new formatting system
This commit is contained in:
parent
acaa4f42e6
commit
ab63c34827
129
src/cpptrace.cpp
129
src/cpptrace.cpp
@ -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);
|
||||||
|
}
|
||||||
|
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) {
|
std::ostream& operator<<(std::ostream& stream, const stacktrace_frame& frame) {
|
||||||
stream
|
return stream << frame.to_string();
|
||||||
<< 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
@ -236,7 +194,7 @@ namespace cpptrace {
|
|||||||
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);
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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());
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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*)#
|
const auto* ptr = (std::uint8_t*)#
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user