Added formatter for exceptions.

This commit is contained in:
Patrick Wuttke 2025-08-30 00:30:47 +02:00
parent d76e64c062
commit a95885880f

View File

@ -4,8 +4,11 @@
#ifndef MIJIN_UTIL_EXCEPTION_HPP_INCLUDED #ifndef MIJIN_UTIL_EXCEPTION_HPP_INCLUDED
#define MIJIN_UTIL_EXCEPTION_HPP_INCLUDED 1 #define MIJIN_UTIL_EXCEPTION_HPP_INCLUDED 1
#include <format>
#include <stdexcept> #include <stdexcept>
#include <typeinfo>
#include "../detect.hpp"
#include "../debug/stacktrace.hpp" #include "../debug/stacktrace.hpp"
namespace mijin namespace mijin
@ -73,5 +76,76 @@ void walkExceptionCause(const std::exception_ptr& cause, TFunc func)
} }
} }
} }
template<typename TFunc>
void walkException(const std::exception& exc, TFunc func)
{
func(exc);
}
template<typename TFunc>
void walkException(const mijin::Exception& exc, TFunc func)
{
func(exc);
walkExceptionCause(exc.getCause(), func);
}
} // namespace mijin } // namespace mijin
template<typename TChar>
struct std::formatter<mijin::Exception, TChar>
{
using char_t = TChar;
template<class TContext>
constexpr TContext::iterator parse(TContext& ctx)
{
auto it = ctx.begin();
auto end = ctx.end();
if (it != end && *it != MIJIN_SMART_QUOTE(char_t, '}'))
{
throw std::format_error("invalid format");
}
return it;
}
template<typename TContext>
TContext::iterator format(const mijin::Exception& exception, TContext& ctx) const
{
using namespace std::literals;
auto it = ctx.out();
bool first = true;
mijin::walkException(exception, [&]<typename T>(const T& exc)
{
if constexpr (!std::is_same_v<T, std::nullptr_t>)
{
if (!first) {
it = std::ranges::copy(MIJIN_SMART_QUOTE(char_t, "\nCaused by:\n"sv), it).out;
}
first = false;
#if MIJIN_RTTI
it = std::ranges::copy(std::basic_string_view(typeid(exc).name()), it).out;
it = std::ranges::copy(MIJIN_SMART_QUOTE(char_t, ": "sv), it).out;
#endif
it = std::ranges::copy(std::basic_string_view(exc.what()), it).out;
if constexpr (std::is_same_v<T, mijin::Exception>)
{
if (const mijin::Result<mijin::Stacktrace>& trace = exc.getStacktrace(); trace.isSuccess())
{
*it = MIJIN_SMART_QUOTE(char_t, '\n');
++it;
it = std::format_to(it, MIJIN_SMART_QUOTE(char_t, "{}"), trace.getValue());
}
}
}
else
{
it = std::ranges::copy(MIJIN_SMART_QUOTE(char_t, "<unknown exception>"sv), it).out;
}
});
return it;
}
};
#endif // MIJIN_UTIL_EXCEPTION_HPP_INCLUDED #endif // MIJIN_UTIL_EXCEPTION_HPP_INCLUDED