#include "error-codes.h" #include "General_Purpose_Allocator.h" #include // vsnprintf, printf #include // 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(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(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; }