146 lines
4.2 KiB
C++
146 lines
4.2 KiB
C++
#pragma once
|
|
#ifndef _NB_ERROR
|
|
#define _NB_ERROR
|
|
|
|
#include <exception>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include <unordered_map>
|
|
|
|
#ifndef THROW
|
|
#ifdef CODE_ERROR_LOCATIONS
|
|
#define THROW(type, ...) throw type(__VA_ARGS__, __LINE__, __FILE__)
|
|
#else
|
|
#define THROW(type, ...) throw type(__VA_ARGS__)
|
|
#endif
|
|
#endif
|
|
|
|
namespace nb {
|
|
|
|
typedef std::unordered_map<unsigned int, const char*> ErrorCodeMap;
|
|
|
|
template<class ErrorType>
|
|
class ErrorBase : public std::exception {
|
|
public:
|
|
ErrorBase(
|
|
const unsigned int code,
|
|
unsigned int line=0,
|
|
std::string filename=""
|
|
) noexcept : ErrorBase(
|
|
code,
|
|
ErrorBase<ErrorType>::lookup(code),
|
|
line,
|
|
filename
|
|
) {}
|
|
ErrorBase(
|
|
const unsigned int code,
|
|
const std::exception& trace,
|
|
unsigned int line=0,
|
|
std::string filename=""
|
|
) noexcept : ErrorBase(
|
|
code,
|
|
ErrorBase<ErrorType>::lookup(code),
|
|
trace,
|
|
line,
|
|
filename
|
|
) {}
|
|
|
|
static std::string lookup(unsigned int);
|
|
unsigned int code() const noexcept {
|
|
return static_cast<const ErrorType*>(this)->_code;
|
|
};
|
|
virtual const char* what() const noexcept override final { return _msg.c_str(); };
|
|
|
|
protected:
|
|
ErrorBase() = default;
|
|
ErrorBase(
|
|
const unsigned int code,
|
|
std::string msg,
|
|
unsigned int line=0,
|
|
std::string filename=""
|
|
) noexcept : _code{code}, _msg{""} {
|
|
static_assert(std::is_same<const std::unordered_map<unsigned int, const char*>, decltype(ErrorType::ErrorMessages)>::value,
|
|
"const std::unordered_map<unsigned int, const char*> ErrorMessages must be "
|
|
"a class member."
|
|
);
|
|
static_assert(std::is_enum_v<typename ErrorType::ErrorCodes>, "enum ErrorCodes must be a class member.");
|
|
static_assert(std::is_same<std::underlying_type_t<typename ErrorType::ErrorCodes>, unsigned int>::value,
|
|
"enum ErrorCodes must be of underlying type unsigned int."
|
|
);
|
|
static_assert(std::is_same<const std::string, decltype(ErrorType::type)>::value,
|
|
"const std::string type must be a class member."
|
|
);
|
|
|
|
_msg += std::string(ErrorType::type);
|
|
_msg += "." + std::to_string(_code);
|
|
if (line && filename.size()) {
|
|
_msg += " in \'" + filename + "\':" + std::to_string(line);
|
|
}
|
|
_msg += "\n " + msg;
|
|
}
|
|
ErrorBase(
|
|
const unsigned int code,
|
|
std::string msg,
|
|
const std::exception& trace,
|
|
unsigned int line=0,
|
|
std::string filename=""
|
|
) noexcept : ErrorBase(code, msg, line, filename) {
|
|
std::string what_msg(trace.what());
|
|
std::string::size_type newline_pos=-1;
|
|
while((newline_pos=what_msg.find("\n", newline_pos+1))!= std::string::npos) {
|
|
what_msg.replace(newline_pos, 1, "\n ");
|
|
}
|
|
_msg += "\n Trace: " + what_msg;
|
|
}
|
|
|
|
unsigned int _code;
|
|
std::string _msg;
|
|
};
|
|
|
|
class Error : public ErrorBase<Error> {
|
|
public:
|
|
enum ErrorCodes : unsigned int {
|
|
GENERAL, UNDEFINED, BADERRORCODE
|
|
};
|
|
|
|
using ErrorBase<Error>::ErrorBase;
|
|
//Error(unsigned int code) : ErrorBase<Error>(code, ErrorBase<Error>::lookup(code)) {}
|
|
//Error(unsigned int code, const std::exception& trace, unsigned int line=0, const std::string& filename="")
|
|
// : ErrorBase<Error>(code, ErrorBase<Error>::lookup(code), trace, line, filename) {}
|
|
|
|
friend ErrorBase<Error>;
|
|
|
|
protected:
|
|
static const std::string type;
|
|
static const ErrorCodeMap ErrorMessages;
|
|
|
|
};
|
|
|
|
/*
|
|
template<class ErrorType>
|
|
ErrorBase<ErrorType>::ErrorBase(
|
|
unsigned int code,
|
|
std::string msg,
|
|
const std::exception& trace,
|
|
unsigned int line,
|
|
std::string filename
|
|
) noexcept
|
|
: ErrorBase<ErrorType>(code, msg, std::make_shared<Error>(trace), line, filename) {}
|
|
*/
|
|
|
|
template<class ErrorType>
|
|
std::string ErrorBase<ErrorType>::lookup(unsigned int code) {
|
|
for (auto kv : ErrorType::ErrorMessages) {
|
|
if (kv.first==code) {
|
|
return std::string(kv.second);
|
|
}
|
|
}
|
|
|
|
throw Error(Error::ErrorCodes::BADERRORCODE);
|
|
}
|
|
|
|
} // namespace nb
|
|
|
|
|
|
#endif // _NB_ERROR
|