#pragma once #include #include #include #include "FormatTuple.hpp" #include "strerror.h" #define EGGS_EXCEPTION(...) EggsException(__LINE__, SHORT_FILE, removeTemplates(__PRETTY_FUNCTION__).c_str(), VALIDATE_FORMAT(__VA_ARGS__)) #define SYSCALL_EXCEPTION(...) SyscallException(__LINE__, SHORT_FILE, removeTemplates(__PRETTY_FUNCTION__).c_str(), errno, VALIDATE_FORMAT(__VA_ARGS__)) #define EXPLICIT_SYSCALL_EXCEPTION(rc, ...) SyscallException(__LINE__, SHORT_FILE, removeTemplates(__PRETTY_FUNCTION__).c_str(), rc, VALIDATE_FORMAT(__VA_ARGS__)) #define FATAL_EXCEPTION(...) FatalException(__LINE__, SHORT_FILE, removeTemplates(__PRETTY_FUNCTION__).c_str(), VALIDATE_FORMAT(__VA_ARGS__)) std::string removeTemplates(const std::string & s); const char *translateErrno(int _errno); class AbstractException : public std::exception { public: virtual const char *what() const throw() override = 0; }; class EggsException : public AbstractException { public: template EggsException(int line, const char *file, const char *function, TFmt fmt, Args ... args); virtual const char *what() const throw() override; private: std::string _msg; }; class SyscallException : public AbstractException { public: template SyscallException(int line, const char *file, const char *function, int capturedErrno, const char *format, Args ... args); virtual const char *what() const throw() override; private: int _errno; std::string _msg; }; class FatalException : public AbstractException { public: template FatalException(int line, const char *file, const char *function, const char *format, Args ... args); virtual const char *what() const throw() override; private: std::string _msg; }; class AssertionException : public AbstractException { public: template AssertionException(int line, const char *file, const char *function, const char *expr, const char* fmt, Args ... args); AssertionException(int line, const char *file, const char *function, const char *expr) : AssertionException(line, file, function, expr, nullptr) {} virtual const char *what() const throw() override { return _msg.c_str(); } private: std::string _msg; }; template EggsException::EggsException(int line, const char *file, const char *function, TFmt fmt, Args ... args) { std::stringstream ss; ss << "EggsException(" << file << "@" << line << " in " << function << "):\n"; format_pack(ss, fmt, args...); _msg = ss.str(); } template SyscallException::SyscallException(int line, const char *file, const char *function, int capturedErrno, const char *fmt, Args ... args) : _errno(capturedErrno) { const char* errmsg = safe_strerror(_errno); std::stringstream ss; ss << "SyscallException(" << file << "@" << line << ", " << _errno << "/" << translateErrno(_errno) << "=" << errmsg << " in " << function << "): "; format_pack(ss, fmt, args...); _msg = ss.str(); } template FatalException::FatalException(int line, const char *file, const char *function, const char *fmt, Args ... args) { std::stringstream ss; ss << "FatalException(" << file << "@" << line << " in " << function << "): "; format_pack(ss, fmt, args...); _msg = ss.str(); } template AssertionException::AssertionException(int line, const char *file, const char *function, const char *expr, const char* fmt, Args ... args) { std::stringstream ss; ss << "AssertionException(" << file << "@" << line << " in " << function << "):\n"; ss << "Expected: " << expr; if (fmt != nullptr && fmt[0] != '\0') { ss << "\nMessage: "; format_pack(ss, fmt, args...); } _msg = ss.str(); }