Add some utilities for exception handling and detecting whether stderr is a terminal

This commit is contained in:
Jeremy 2023-10-07 14:59:04 -04:00
parent df6c22f640
commit 8bb8a2020c
No known key found for this signature in database
GPG Key ID: 19AA8270105E8EB4
5 changed files with 49 additions and 7 deletions

View File

@ -145,7 +145,7 @@ namespace cpptrace {
void print() const; void print() const;
void print(std::ostream& stream) const; void print(std::ostream& stream) const;
void print(std::ostream& stream, bool color) const; void print(std::ostream& stream, bool color) const;
std::string to_string() const; std::string to_string(bool color = false) const;
void clear(); void clear();
bool empty() const noexcept; bool empty() const noexcept;
/* operator<<(ostream, ..), std::format support, and iterators exist for this object */ /* 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 speed is prioritized. If using this function, set the cache mode at the very start of your program before any traces are
performed. performed.
`cpptrace::isatty` and the fileno definitions are useful for deciding whether to use color when printing stack taces.
```cpp ```cpp
namespace cpptrace { namespace cpptrace {
std::string demangle(const std::string& name); std::string demangle(const std::string& name);
void absorb_trace_exceptions(bool absorb); 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 { enum class cache_mode {
// Only minimal lookup tables // Only minimal lookup tables

View File

@ -2,7 +2,6 @@
#define CPPTRACE_HPP #define CPPTRACE_HPP
#include <cstdint> #include <cstdint>
#include <cstdio>
#include <exception> #include <exception>
#include <ostream> #include <ostream>
#include <string> #include <string>
@ -103,7 +102,7 @@ namespace cpptrace {
CPPTRACE_API void print(std::ostream& stream, bool color) const; CPPTRACE_API void print(std::ostream& stream, bool color) const;
CPPTRACE_API void clear(); CPPTRACE_API void clear();
CPPTRACE_API bool empty() const noexcept; 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); CPPTRACE_API friend std::ostream& operator<<(std::ostream& stream, const stacktrace& trace);
using iterator = std::vector<stacktrace_frame>::iterator; using iterator = std::vector<stacktrace_frame>::iterator;
@ -127,8 +126,13 @@ namespace cpptrace {
// utilities: // utilities:
CPPTRACE_API std::string demangle(const std::string& name); 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 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 { enum class cache_mode {
// Only minimal lookup tables // Only minimal lookup tables
prioritize_memory, prioritize_memory,

View File

@ -3,6 +3,7 @@
#include <atomic> #include <atomic>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstdio>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@ -233,9 +234,9 @@ namespace cpptrace {
} }
CPPTRACE_API CPPTRACE_API
std::string stacktrace::to_string() const { std::string stacktrace::to_string(bool color) const {
std::ostringstream oss; std::ostringstream oss;
print(oss, false, false); print(oss, color, false);
return std::move(oss).str(); return std::move(oss).str();
} }
@ -318,6 +319,15 @@ namespace cpptrace {
return detail::demangle(name); 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 { namespace detail {
std::atomic_bool absorb_trace_exceptions(true); // NOSONAR std::atomic_bool absorb_trace_exceptions(true); // NOSONAR
std::atomic<enum cache_mode> cache_mode(cache_mode::prioritize_speed); // NOSONAR std::atomic<enum cache_mode> cache_mode(cache_mode::prioritize_speed); // NOSONAR

View File

@ -22,12 +22,30 @@
#if IS_WINDOWS #if IS_WINDOWS
#include <windows.h> #include <windows.h>
#include <io.h>
#else #else
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h>
#endif #endif
namespace cpptrace { namespace cpptrace {
namespace detail { 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<std::string> split(const std::string& str, const std::string& delims) { inline std::vector<std::string> split(const std::string& str, const std::string& delims) {
std::vector<std::string> vec; std::vector<std::string> vec;
size_t old_pos = 0; size_t old_pos = 0;

View File

@ -6,8 +6,8 @@
#include <string> #include <string>
void trace() { void trace() {
cpptrace::absorb_trace_exceptions(false);
cpptrace::generate_trace().print(); cpptrace::generate_trace().print();
throw cpptrace::exception_with_message("foobar");
} }
void foo(int n) { void foo(int n) {
@ -35,5 +35,8 @@ int main() try {
cpptrace::absorb_trace_exceptions(false); cpptrace::absorb_trace_exceptions(false);
function_one(0); function_one(0);
} catch(cpptrace::exception& e) { } 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));
} }