/** * Copyright (c) 2025 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #pragma once #include "dusk.h" typedef uint8_t errorcode_t; typedef struct { errorcode_t code; char_t *message; char_t *lines; } errorstate_t; typedef struct { errorcode_t code; errorstate_t *state; } errorret_t; static const errorcode_t ERROR_OK = 0; static const errorcode_t ERROR_NOT_OK = 1; static const char_t *ERROR_PRINT_FORMAT = "Error (%d): %s\n%s"; static const char_t *ERROR_LINE_FORMAT = " at %s:%d in function %s\n"; static errorstate_t ERROR_STATE = { .code = ERROR_OK, .message = NULL, .lines = NULL }; /** * Sets the error state with the provided code and message. * * @param state The error state to initialize. * @param code The error code to set. * @param file The file where the error occurred. * @param function The function where the error occurred. * @param line The line number where the error occurred. * @param message The error message. * @param args The arguments for the error message. * @return The error code. */ errorret_t errorThrowImpl( errorstate_t *state, errorcode_t code, const char_t *file, const char_t *function, const int32_t line, const char_t *message, ... ); /** * Returns an error state with no error. * * @return An error state with code ERROR_OK. */ errorret_t errorOkImpl(); /** * Chains an error state, allowing for error propagation. * * @param retval The return value containing the error state. * @param file The file where the error occurred. * @param function The function where the error occurred. * @param line The line number where the error occurred. * @return The error code if an error occurred, otherwise continues execution. */ errorret_t errorChainImpl( const errorret_t retval, const char_t *file, const char_t *function, const int32_t line ); /** * Catches an error and handles it. * * @param retval The return value containing the error state. */ void errorCatch(const errorret_t retval); /** * Prints the error state to the console. * * @param retval The return value containing the error state. * @return Passed retval for chaining. */ errorret_t errorPrint(const errorret_t retval); /** * Throws an error with a formatted message. * * @param code The error code to throw. * @param message The format string for the error message. * @param ... Additional arguments for the format string. * @return The error code. */ #define errorThrowWithCode(code, message, ... ) \ return errorThrowImpl(\ &ERROR_STATE, (code), __FILE__, __func__, __LINE__, (message), \ __VA_ARGS__ \ ) /** * Throws an error with a default error code of ERROR_NOT_OK. * * @param message The format string for the error message. * @param ... Additional arguments for the format string. * @return The error code. */ #define errorThrow(message, ...) \ return errorThrowImpl(\ &ERROR_STATE, ERROR_NOT_OK, __FILE__, __func__, __LINE__, (message), \ __VA_ARGS__ \ ) /** * Checks if a child method errored, and if it did, then send it up the chain. * @param retval The return value containing the error state. * @return The error code if an error occurred, otherwise continues execution. */ #define errorChain(retval) \ if ((retval).code != ERROR_OK) { \ return errorChainImpl(retval, __FILE__, __func__, __LINE__); \ } /** * Returns without an error. */ #define errorOk() \ return errorOkImpl() // EOF