Musa-Cpp-Lib-V2/lib/Base/ErrorCodes.cpp
2025-11-23 04:09:52 -05:00

166 lines
4.9 KiB
C++

enum ErrorSeverity: s32 {
SEVERITY_WARNING = 0,
SEVERITY_NON_FATAL = 1,
SEVERITY_FATAL = 2
};
// typedef struct string Native_Error;
// Note: Native_Error should down-cast to a string.
struct Native_Error {
s64 count;
u8* data;
ErrorSeverity severity = SEVERITY_WARNING;
};
#define Null_Pointer_Check(arg) \
if (arg == nullptr) { \
return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is a null pointer.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); \
}
#define Array_Check(arg) \
if (!is_valid(arg)) { \
return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is not a valid array.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); \
}
#define String_Check(arg) \
if (!Is_Valid(arg)) { return New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s is not a valid string.", __FILE__, __LINE__, __FUNCTION__, Stringify(arg)); }
#define Error_Check(error) \
if (error != nullptr) { \
return error; \
}
// An error from which the program cannot continue (e.g. a segmentation fault)
#define New_Fatal_Error(message) \
New_Fatal_Error_Internal("%s:%d\n[%s] Error: %s.", __FILE__, __LINE__, __FUNCTION__, message)
#define New_Error(message) \
New_Error_Internal("%s:%d\n[%s] Error: %s.", __FILE__, __LINE__, __FUNCTION__, message)
#define New_Warning(message) \
New_Warning_Internal("%s:%d\n[%s] Warning: %s.", __FILE__, __LINE__, __FUNCTION__, message)
Native_Error* New_Fatal_Error_Internal(char* raw_message, ...);
Native_Error* New_Error_Internal(char* raw_message, ...);
Native_Error* New_Warning_Internal(char* raw_message, ...);
Native_Error* Native_Error_Callstack(Native_Error* new_error, Native_Error* old_error, ErrorSeverity severity);
PROTOTYPING_API C_API Native_Error* Cleanup_Error(Native_Error* error);
PROTOTYPING_API C_API Native_Error* Native_Error_Test();
#include "General_Purpose_Allocator.h"
#include <stdio.h> // vsnprintf, printf
#include <cstdarg> // va_list...
#define BREAK_ON_WARNINGS 0
#define BREAK_ON_ERRORS 0
#define BREAK_ON_FATAL_ERROR BUILD_DEBUG
#define ALWAYS_PRINT_ERROR_MESSAGES BUILD_DEBUG
Native_Error* Create_New_Native_Error_Internal(char* format, va_list args) {
constexpr s64 ERROR_BUFFER_COUNT = 512;
// push_allocator(GPAllocator());
auto error = New<Native_Error>(false);
error->data = (u8*)GPAllocator_New(ERROR_BUFFER_COUNT);
// You MUST copy the va_list before using it more than once
va_list args_copy;
va_copy(args_copy, args);
error->count = (s64)vsnprintf((char*)error->data, (size_t)ERROR_BUFFER_COUNT, format, args_copy);
va_end(args_copy);
return error;
}
Native_Error* New_Fatal_Error_Internal(char* format, ...) {
va_list args;
va_start(args, format);
auto error = Create_New_Native_Error_Internal(format, args);
va_end(args);
error->severity = SEVERITY_FATAL;
#if BUILD_DEBUG && ALWAYS_PRINT_ERROR_MESSAGES
printf("[FATAL ERROR] %.*s\n", (s32)error->count, (char*)error->data);
#endif
#if BREAK_ON_FATAL_ERROR
debug_break();
#endif
return error;
}
Native_Error* Native_Error_Callstack(Native_Error* new_error, Native_Error* old_error, ErrorSeverity severity) {
// push_allocator(GPAllocator());
auto error_message = format_string("%s\n > %s", new_error->data, old_error->data).data;
Cleanup_Error(new_error);
Cleanup_Error(old_error);
Native_Error* error_merged = New<Native_Error>(false);
error_merged->data = (u8*)error_message;
error_merged->count = strlen((char*)error_merged->data);
error_merged->severity = severity;
return error_merged;
}
Native_Error* Native_Error_Test() {
// This is quite verbose, but w/e
auto old_error = New_Error("Original error...");
auto new_message = format_string("Failed to start stream. Error Code: %d", -1).data;
auto new_error = New_Error(new_message);
GPAllocator_Delete(new_message);
return Native_Error_Callstack(new_error, old_error, SEVERITY_NON_FATAL);
}
Native_Error* New_Error_Internal(char* format, ...) {
va_list args;
va_start(args, format);
auto error = Create_New_Native_Error_Internal(format, args);
va_end(args);
error->severity = SEVERITY_NON_FATAL;
#if BUILD_DEBUG && ALWAYS_PRINT_ERROR_MESSAGES
printf("[ERROR (NON-FATAL)] %.*s\n", (s32)error->count, (char*)error->data);
#endif
#if BREAK_ON_ERRORS
debug_break();
#endif
return error;
}
Native_Error* New_Warning_Internal(char* format, ...) {
va_list args;
va_start(args, format);
auto error = Create_New_Native_Error_Internal(format, args);
va_end(args);
error->severity = SEVERITY_WARNING;
#if BUILD_DEBUG && ALWAYS_PRINT_ERROR_MESSAGES
printf("[WARNING] %.*s\n", (s32)error->count, (char*)error->data);
#endif
#if BREAK_ON_WARNINGS
debug_break();
#endif
return error;
}
Native_Error* Cleanup_Error(Native_Error* error) {
if (error == nullptr) return nullptr;
GPAllocator_Delete(error->data);
GPAllocator_Delete(error);
return nullptr;
}