78 lines
1.7 KiB
C++
78 lines
1.7 KiB
C++
|
|
#pragma once
|
|
|
|
#ifndef MIJIN_UTIL_EXCEPTION_HPP_INCLUDED
|
|
#define MIJIN_UTIL_EXCEPTION_HPP_INCLUDED 1
|
|
|
|
#include <stdexcept>
|
|
|
|
#include "../debug/stacktrace.hpp"
|
|
|
|
namespace mijin
|
|
{
|
|
|
|
//
|
|
// public defines
|
|
//
|
|
|
|
//
|
|
// public types
|
|
//
|
|
|
|
class Exception : public std::runtime_error
|
|
{
|
|
private:
|
|
Result<Stacktrace> stacktrace_;
|
|
std::exception_ptr cause_;
|
|
public:
|
|
Exception(const std::string& what) : std::runtime_error(what), stacktrace_(captureStacktrace(1)), cause_(std::current_exception()) {}
|
|
Exception(const char* what) : Exception(std::string(what)) {}
|
|
|
|
[[nodiscard]]
|
|
const Result<Stacktrace>& getStacktrace() const noexcept { return stacktrace_; }
|
|
|
|
[[nodiscard]]
|
|
const std::exception_ptr& getCause() const noexcept { return cause_; }
|
|
};
|
|
|
|
//
|
|
// public functions
|
|
//
|
|
|
|
template<typename TCondition, typename TException = std::runtime_error, typename... TExceptionArgs>
|
|
inline decltype(auto) ensure(TCondition&& condition, TExceptionArgs&&... args)
|
|
{
|
|
if (!static_cast<bool>(std::forward<TCondition>(condition)))
|
|
{
|
|
throw TException(std::forward<TExceptionArgs>(args)...);
|
|
}
|
|
return std::forward<TCondition>(condition);
|
|
}
|
|
|
|
template<typename TFunc>
|
|
void walkExceptionCause(const std::exception_ptr& cause, TFunc func)
|
|
{
|
|
if (cause)
|
|
{
|
|
try
|
|
{
|
|
std::rethrow_exception(cause);
|
|
}
|
|
catch(Exception& exc)
|
|
{
|
|
func(exc);
|
|
walkExceptionCause(exc.getCause(), std::move(func));
|
|
}
|
|
catch(std::exception& exc)
|
|
{
|
|
func(exc);
|
|
}
|
|
catch(...)
|
|
{
|
|
func(nullptr);
|
|
}
|
|
}
|
|
}
|
|
} // namespace mijin
|
|
#endif // MIJIN_UTIL_EXCEPTION_HPP_INCLUDED
|