feat: add assertion library
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
#include "assert.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#ifdef _WIN32
|
||||
// from: WinUser.h
|
||||
#ifndef MB_ICONHAND
|
||||
#define MB_ICONHAND 0x00000010L
|
||||
#define MB_ICONERROR MB_ICONHAND
|
||||
|
||||
#define MB_SYSTEMMODAL 0x00001000L
|
||||
|
||||
#define MB_OK 0x00000000L
|
||||
#endif
|
||||
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport) void* __stdcall GetModuleHandleA(const char* lpModuleName);
|
||||
__declspec(dllimport) void* __stdcall LoadLibraryA(const char* lpLibFileName);
|
||||
__declspec(dllimport) int(__stdcall* __stdcall GetProcAddress(void* hModule, const char* lpProcName))();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __linux
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
std::string safeShellEscape(const std::string& input)
|
||||
{
|
||||
std::string escaped;
|
||||
for (char c : input)
|
||||
{
|
||||
if (c == '"' || c == '\\' || c == '`' || c == '$') escaped += '\\';
|
||||
escaped += c;
|
||||
}
|
||||
return escaped;
|
||||
}
|
||||
|
||||
void seallib::displayError(const char* msg, const char* file, int line)
|
||||
{
|
||||
std::string fullError = std::string(msg) + "\n\nFile: " + file + "\nLine: " + std::to_string(line);
|
||||
std::cerr << "[FATAL ERROR] " << fullError << std::endl;
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef int(__stdcall * fnMessageBoxA)(void*, const char*, const char*, unsigned int);
|
||||
if (void* hUser32 = GetModuleHandleA("user32.dll") ? GetModuleHandleA("user32.dll") : LoadLibraryA("user32.dll"))
|
||||
{
|
||||
auto msgBoxA = reinterpret_cast<fnMessageBoxA>(GetProcAddress(hUser32, "MessageBoxA"));
|
||||
if (msgBoxA) msgBoxA(nullptr, fullError.c_str(), "Fatal Error Occurred", MB_ICONERROR | MB_OK | MB_SYSTEMMODAL);
|
||||
}
|
||||
#elif __linux__
|
||||
std::string safeMsg = safeShellEscape(fullError);
|
||||
if (std::system("which zenity > /dev/null 2>&1") == 0)
|
||||
std::system(("zenity --error --text=\"" + safeMsg + "\" --title=\"Fatal Error\" 2>/dev/null").c_str());
|
||||
else if (std::system("which kdialog > /dev/null 2>&1") == 0)
|
||||
std::system(("kdialog --error \"" + safeMsg + "\" 2>/dev/null").c_str());
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define SEALLIB_DEBUGBREAK() __debugbreak()
|
||||
#define SEALLIB_ASSUME(cond) __assume(cond)
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#define SEALLIB_DEBUGBREAK() __builtin_trap()
|
||||
#define SEALLIB_ASSUME(cond) \
|
||||
do \
|
||||
{ \
|
||||
if (!(cond)) __builtin_unreachable(); \
|
||||
} while (0)
|
||||
#else
|
||||
#define SEALLIB_DEBUGBREAK() \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define SEALLIB_ASSUME(cond) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define ASSERT(cond, msg) \
|
||||
do \
|
||||
{ \
|
||||
if (!(cond)) \
|
||||
{ \
|
||||
seallib::displayError(msg, __FILE__, __LINE__); \
|
||||
SEALLIB_DEBUGBREAK(); \
|
||||
std::exit(EXIT_FAILURE); \
|
||||
} \
|
||||
SEALLIB_ASSUME(cond); \
|
||||
} while (0)
|
||||
#else
|
||||
#define ASSERT(cond, msg) SEALLIB_ASSUME(cond)
|
||||
#endif
|
||||
|
||||
#define PANIC(msg) \
|
||||
do \
|
||||
{ \
|
||||
seallib::displayError(msg, __FILE__, __LINE__); \
|
||||
SEALLIB_DEBUGBREAK(); \
|
||||
std::exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
namespace seallib
|
||||
{
|
||||
void displayError(const char* msg, const char* file, int line);
|
||||
}
|
||||
Reference in New Issue
Block a user