Riyyi
2 years ago
1 changed files with 97 additions and 0 deletions
@ -0,0 +1,97 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Riyyi |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: MIT |
||||||
|
*/ |
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <cstddef> // size_t |
||||||
|
#include <cstdint> // uint32_t |
||||||
|
#include <cstring> // strlen |
||||||
|
#include <fstream> // ifstream |
||||||
|
#include <string> |
||||||
|
|
||||||
|
#include "util/format/format.h" |
||||||
|
#include "util/meta/compiler.h" |
||||||
|
|
||||||
|
#define CRASH() asm volatile("int $0x03"); |
||||||
|
|
||||||
|
#ifndef NDEBUG |
||||||
|
#define VERIFY(expr, ...) (static_cast<bool>(expr) ? (void)0 : Util::__assertion_failed(#expr, __FILE__, __LINE__, FUNCTION_MACRO __VA_OPT__(, ) __VA_ARGS__)) |
||||||
|
#define VERIFY_NOT_REACHED() VERIFY(false) |
||||||
|
#else |
||||||
|
#define VERIFY(expr, ...) (static_cast<bool>(expr) ? (void)0 : CRASH() |
||||||
|
#define VERIFY_NOT_REACHED() CRASH() |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef NDEBUG |
||||||
|
namespace Util { |
||||||
|
|
||||||
|
template<typename... Parameters> |
||||||
|
inline void __assertion_failed(const char* assertion, const char* file, uint32_t line, const char* function, const Parameters&... parameters) |
||||||
|
{ |
||||||
|
// Get the line that caused the error
|
||||||
|
std::ifstream source(file); |
||||||
|
std::string content; |
||||||
|
if (source.is_open()) { |
||||||
|
for (uint32_t i = 0; std::getline(source, content); ++i) { |
||||||
|
if (i == line - 1) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// Replace tab indentation with spaces
|
||||||
|
size_t tabs = content.find_first_not_of('\t'); |
||||||
|
if (tabs > 0 && tabs < content.size()) { |
||||||
|
content = std::string(tabs * 4, ' ') + content.substr(tabs); |
||||||
|
} |
||||||
|
|
||||||
|
// Find the assertion in the line
|
||||||
|
size_t column = content.find(assertion); |
||||||
|
size_t assertionLength = strlen(assertion); |
||||||
|
if (column == std::string::npos) { |
||||||
|
column = content.find_first_not_of(' '); |
||||||
|
assertionLength = content.length() - column; |
||||||
|
} |
||||||
|
|
||||||
|
// Error message
|
||||||
|
fprintf(stderr, |
||||||
|
"\033[;1m%s:%u:%zu " |
||||||
|
"\033[31;1merror: " |
||||||
|
"\033[0massertion failed", |
||||||
|
file, line, column + 1); |
||||||
|
if constexpr (sizeof...(Parameters) > 0) { |
||||||
|
fprintf(stderr, ": "); |
||||||
|
// Cant use the formatting library to print asserts caused by the formatting library
|
||||||
|
if (!std::string_view(function).starts_with("Util::Format::")) { |
||||||
|
std::string message; |
||||||
|
strln(message, parameters...); |
||||||
|
fprintf(stderr, "%s", message.c_str()); |
||||||
|
} |
||||||
|
else { |
||||||
|
fprintf(stderr, parameters...); |
||||||
|
fprintf(stderr, "\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
fprintf(stderr, "\n"); |
||||||
|
} |
||||||
|
|
||||||
|
// Code line
|
||||||
|
fprintf(stderr, " %u | %s\033[31;1m%s\033[0m%s\n", line, |
||||||
|
content.substr(0, column).c_str(), // Whitespace at front
|
||||||
|
content.substr(column, assertionLength).c_str(), // Error portion
|
||||||
|
content.substr(column + assertionLength).c_str()); // Rest of the line
|
||||||
|
|
||||||
|
// Arrow pointer
|
||||||
|
fprintf(stderr, " %s | %s\033[31;1m^%s\033[0m\n", |
||||||
|
std::string(std::to_string(line).length(), ' ').c_str(), // Line number spacing
|
||||||
|
std::string(column, ' ').c_str(), // Content spacing
|
||||||
|
std::string(assertionLength - 1, '~').c_str()); // Arrow pointer
|
||||||
|
|
||||||
|
CRASH(); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace Util
|
||||||
|
#endif |
Loading…
Reference in new issue