2025-01-22 17:22:38 +01:00

201 lines
5.0 KiB
C

#pragma once
#include <kinc/global.h>
#include <stdarg.h>
/*! \file error.h
\brief Contains functionality to stop the program in case of an error and create a user-visible error message.
The affirm and error functions print an error message and then exit the program. Error messages can be made
visible to the user (unless a console window is active this is only implemented for Windows).
*/
#ifdef __cplusplus
extern "C" {
#endif
/// <summary>
/// Exits the program when a condition is untrue and shows
/// a generic error message.
/// </summary>
/// <remarks>
/// This is an alternative to assert which also persists in release
/// builds. Use this instead of assert in situations where you want
/// your users to see what's going wrong.
/// This uses Kinc's log and error functionality to make errors
/// visible.
/// </remarks>
/// <param name="condition">
/// Exits the program if condition is false,
/// otherwise does nothing.
/// </param>
KINC_FUNC void kinc_affirm(bool condition);
/// <summary>
/// Exits the program when a condition is untrue and shows
/// a provided error message.
/// </summary>
/// <remarks>
/// This is equivalent to kinc_affirm() but uses the provided message
/// instead of a generic one.
/// </remarks>
/// <param name="condition">
/// Exits the program if condition is false,
/// otherwise does nothing.
/// </param>
/// <param name="format">
/// The parameter is equivalent to the first printf parameter.
/// </param>
/// <param name="...">
/// The parameter is equivalent to the second printf parameter.
/// </param>
KINC_FUNC void kinc_affirm_message(bool condition, const char *format, ...);
/// <summary>
/// Equivalent to kinc_affirm_message but uses a va_list parameter.
/// </summary>
/// <remarks>
/// You will need this if you want to provide the parameters using va_start/va_end.
/// </remarks>
/// <param name="condition">
/// Exits the program if condition is false,
/// otherwise does nothing.
/// </param>
/// <param name="format">
/// The parameter is equivalent to the first vprintf parameter.
/// </param>
/// <param name="...">
/// The parameter is equivalent to the second vprintf parameter.
/// </param>
KINC_FUNC void kinc_affirm_args(bool condition, const char *format, va_list args);
/// <summary>
/// Exits the program and shows a generic error message
/// </summary>
/// <remarks>
/// Mainly this just calls exit(EXIT_FAILURE) but will also use
/// Kore's log function and on Windows show an error message box.
/// </remarks>
KINC_FUNC void kinc_error(void);
/// <summary>
/// Exits the program and shows a provided error message.
/// </summary>
/// <remarks>
/// This is equivalent to kinc_error() but uses the provided message
/// instead of a generic one.
/// </remarks>
/// <param name="format">
/// The parameter is equivalent to the first printf parameter.
/// </param>
/// <param name="...">
/// The parameter is equivalent to the second printf parameter.
/// </param>
KINC_FUNC void kinc_error_message(const char *format, ...);
/// <summary>
/// Equivalent to kinc_error_message but uses a va_list parameter.
/// </summary>
/// <remarks>
/// You will need this if you want to provide the parameters using va_start/va_end.
/// </remarks>
/// <param name="format">
/// The parameter is equivalent to the first vprintf parameter.
/// </param>
/// <param name="...">
/// The parameter is equivalent to the second vprintf parameter.
/// </param>
KINC_FUNC void kinc_error_args(const char *format, va_list args);
#ifdef KINC_IMPLEMENTATION_ROOT
#define KINC_IMPLEMENTATION
#endif
#ifdef KINC_IMPLEMENTATION
#ifndef KINC_IMPLEMENTATION_ROOT
#undef KINC_IMPLEMENTATION
#endif
#include <kinc/log.h>
#ifndef KINC_IMPLEMENTATION_ROOT
#define KINC_IMPLEMENTATION
#endif
#include <stdlib.h>
#ifdef KORE_WINDOWS
#include <kinc/backend/MiniWindows.h>
#include <kinc/backend/SystemMicrosoft.h>
#endif
void kinc_affirm(bool condition) {
if (!condition) {
kinc_error();
}
}
void kinc_affirm_message(bool condition, const char *format, ...) {
if (!condition) {
va_list args;
va_start(args, format);
kinc_error_args(format, args);
va_end(args);
}
}
void kinc_affirm_args(bool condition, const char *format, va_list args) {
if (!condition) {
kinc_error_args(format, args);
}
}
void kinc_error(void) {
kinc_error_message("Unknown error");
}
void kinc_error_message(const char *format, ...) {
{
va_list args;
va_start(args, format);
kinc_log_args(KINC_LOG_LEVEL_ERROR, format, args);
va_end(args);
}
#ifdef KORE_WINDOWS
{
va_list args;
va_start(args, format);
wchar_t buffer[4096];
kinc_microsoft_format(format, args, buffer);
MessageBoxW(NULL, buffer, L"Error", 0);
va_end(args);
}
#endif
#ifndef KINC_NO_CLIB
exit(EXIT_FAILURE);
#endif
}
void kinc_error_args(const char *format, va_list args) {
kinc_log_args(KINC_LOG_LEVEL_ERROR, format, args);
#ifdef KORE_WINDOWS
wchar_t buffer[4096];
kinc_microsoft_format(format, args, buffer);
MessageBoxW(NULL, buffer, L"Error", 0);
#endif
#ifndef KINC_NO_CLIB
exit(EXIT_FAILURE);
#endif
}
#endif
#ifdef __cplusplus
}
#endif