diff --git a/README.md b/README.md index 1e669da..aa8ddcc 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ namespace cpptrace { void print() const; void print(std::ostream& stream) const; void print(std::ostream& stream, bool color) const; - std::string to_string() const; + std::string to_string(bool color = false) const; void clear(); bool empty() const noexcept; /* operator<<(ostream, ..), std::format support, and iterators exist for this object */ @@ -224,10 +224,17 @@ or wether they're rethrown to the caller. speed is prioritized. If using this function, set the cache mode at the very start of your program before any traces are performed. +`cpptrace::isatty` and the fileno definitions are useful for deciding whether to use color when printing stack taces. + ```cpp namespace cpptrace { std::string demangle(const std::string& name); void absorb_trace_exceptions(bool absorb); + bool isatty(int fd); + + extern const int stdin_fileno; + extern const int stderr_fileno; + extern const int stdout_fileno; enum class cache_mode { // Only minimal lookup tables diff --git a/include/cpptrace/cpptrace.hpp b/include/cpptrace/cpptrace.hpp index 2768e20..f6e1942 100644 --- a/include/cpptrace/cpptrace.hpp +++ b/include/cpptrace/cpptrace.hpp @@ -2,7 +2,6 @@ #define CPPTRACE_HPP #include -#include #include #include #include @@ -103,7 +102,7 @@ namespace cpptrace { CPPTRACE_API void print(std::ostream& stream, bool color) const; CPPTRACE_API void clear(); CPPTRACE_API bool empty() const noexcept; - CPPTRACE_API std::string to_string() const; + CPPTRACE_API std::string to_string(bool color = false) const; CPPTRACE_API friend std::ostream& operator<<(std::ostream& stream, const stacktrace& trace); using iterator = std::vector::iterator; @@ -127,8 +126,13 @@ namespace cpptrace { // utilities: CPPTRACE_API std::string demangle(const std::string& name); + CPPTRACE_API bool isatty(int fd); CPPTRACE_API void absorb_trace_exceptions(bool absorb); + CPPTRACE_API extern const int stdin_fileno; + CPPTRACE_API extern const int stderr_fileno; + CPPTRACE_API extern const int stdout_fileno; + enum class cache_mode { // Only minimal lookup tables prioritize_memory, diff --git a/src/cpptrace.cpp b/src/cpptrace.cpp index 8469b2d..df03241 100644 --- a/src/cpptrace.cpp +++ b/src/cpptrace.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -233,9 +234,9 @@ namespace cpptrace { } CPPTRACE_API - std::string stacktrace::to_string() const { + std::string stacktrace::to_string(bool color) const { std::ostringstream oss; - print(oss, false, false); + print(oss, color, false); return std::move(oss).str(); } @@ -318,6 +319,15 @@ namespace cpptrace { return detail::demangle(name); } + CPPTRACE_API + bool isatty(int fd) { + return detail::isatty(fd); + } + + CPPTRACE_API const int stdin_fileno = detail::fileno(stdin); + CPPTRACE_API const int stdout_fileno = detail::fileno(stdout); + CPPTRACE_API const int stderr_fileno = detail::fileno(stderr); + namespace detail { std::atomic_bool absorb_trace_exceptions(true); // NOSONAR std::atomic cache_mode(cache_mode::prioritize_speed); // NOSONAR diff --git a/src/platform/utils.hpp b/src/platform/utils.hpp index 1e0c2a2..b73c548 100644 --- a/src/platform/utils.hpp +++ b/src/platform/utils.hpp @@ -22,12 +22,30 @@ #if IS_WINDOWS #include + #include #else #include + #include #endif namespace cpptrace { namespace detail { + inline bool isatty(int fd) { + #if IS_WINDOWS + return _isatty(fd); + #else + return ::isatty(fd); + #endif + } + + inline int fileno(FILE* stream) { + #if IS_WINDOWS + return _fileno(stream); + #else + return ::fileno(stream); + #endif + } + inline std::vector split(const std::string& str, const std::string& delims) { std::vector vec; size_t old_pos = 0; diff --git a/test/demo.cpp b/test/demo.cpp index aca84db..c2a3111 100644 --- a/test/demo.cpp +++ b/test/demo.cpp @@ -6,8 +6,8 @@ #include void trace() { - cpptrace::absorb_trace_exceptions(false); cpptrace::generate_trace().print(); + throw cpptrace::exception_with_message("foobar"); } void foo(int n) { @@ -35,5 +35,8 @@ int main() try { cpptrace::absorb_trace_exceptions(false); function_one(0); } catch(cpptrace::exception& e) { - std::cerr << e.what(); + std::cerr << "Error: " + << e.get_raw_what() + << '\n'; + e.get_trace().print(std::cerr, cpptrace::isatty(cpptrace::stderr_fileno)); }