/** * 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; #define ERROR_STATE_INIT ((errorstate_t){ ERROR_OK, NULL, NULL }) 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 = ERROR_STATE_INIT; /** * 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); /** * Creates an error with a specific error state. * * @param state The error state to set. * @param message The format string for the error message. * @param ... Additional arguments for the format string. * @return The error code. */ #define errorCreate(state, message, ... ) \ errorThrowImpl(\ (state), ERROR_NOT_OK, __FILE__, __func__, __LINE__, (message), \ ##__VA_ARGS__ \ ) /** * Throws an error with a specific error state. * * @param state The error state to set. * @param message The format string for the error message. * @param ... Additional arguments for the format string. * @return The error code. */ #define errorThrowState(state, message, ... ) \ return errorThrowImpl(\ (state), ERROR_NOT_OK, __FILE__, __func__, __LINE__, (message), \ ##__VA_ARGS__ \ ) /** * 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) { \ errorret_t errorChainRetval = (retval); \ if (errorChainRetval.code != ERROR_OK) { \ return errorChainImpl(errorChainRetval, __FILE__, __func__, __LINE__); \ } \ } /** * Returns without an error. */ #define errorOk() \ return errorOkImpl() // EOF