diff --git a/Source/DrangPlatform/Include/drang/error.h b/Source/DrangPlatform/Include/drang/error.h index 2ee9f79..06cae3a 100644 --- a/Source/DrangPlatform/Include/drang/error.h +++ b/Source/DrangPlatform/Include/drang/error.h @@ -10,32 +10,75 @@ DRANG_BEGIN_DECLS */ DRANG_API const char *drang_error_str(int err); -#define DRANG_EOK (0) -#define DRANG_EINVAL (-1) -#define DRANG_ENOMEM (-2) -#define DRANG_EIO (-3) -#define DRANG_NOTSUP (-4) -#define DRANG_EAGAIN (-5) -#define DRANG_ENOENT (-6) +#define DRANG_EOK (0) // Success +#define DRANG_EINVAL (-1) // Invalid argument +#define DRANG_ENOMEM (-2) // Out of memory +#define DRANG_EIO (-3) // I/O error +#define DRANG_NOTSUP (-4) // Operation not supported +#define DRANG_EAGAIN (-5) // Resource temporarily unavailable +#define DRANG_ENOENT (-6) // No such file or directory +#define DRANG_EDEADLK (-7) // Resource deadlock would occur +#define DRANG_EPERM (-8) // Operation not permitted +#define DRANG_ETIMEDOUT (-9) // Connection timed out +#define DRANG_EBUSY (-10) // Device or resource busy +/** + * @brief Begins a try-catch block for error handling. + * @details Initializes the error handling mechanism by declaring a local + * variable `_res` and starting a new scope. This macro must be + * paired with either DRANG_END_TRY() or DRANG_END_TRY_IGNORE(). + * @remarks Use this macro at the beginning of a function that needs + * structured error handling. All error-prone operations should + * be wrapped with DRANG_TRY() or DRANG_CHECK(). + */ #define DRANG_BEGIN_TRY() \ int _res = DRANG_EOK; \ { +/** + * @brief Defines a catch block that executes when an error occurs. + * @param name Variable name to hold the error code in the catch block. + * @details This macro closes the try block and starts a catch block that + * only executes if an error occurred (_res != DRANG_EOK). + * @remarks The catch block is required and must be followed by DRANG_END_TRY(). + * If no special handling is needed, use DRANG_END_TRY_IGNORE() instead. + */ #define DRANG_CATCH(name) \ } \ _drang_cleanup: \ if (_res != DRANG_EOK) { \ int name = _res; +/** + * @brief Ends a try-catch block and returns the error code. + * @details Closes any open catch block and returns the current error status. + * If no error occurred, returns DRANG_EOK. + * @remarks This macro must be used to properly close a DRANG_BEGIN_TRY() block. + * The function will return the error code to the caller. + */ #define DRANG_END_TRY() \ } \ return _res; +/** + * @brief Ends a try-catch block when no catch handling is needed. + * @details Similar to DRANG_END_TRY() but provides an empty cleanup label. + * @remarks Use this when you don't need to perform cleanup operations after + * error handling. + */ #define DRANG_END_TRY_IGNORE() \ } \ _drang_cleanup: \ return _res; +/** + * @brief Executes an expression and jumps to clean up on error. + * @param expr Expression that returns a DRANG error code. + * @details Evaluates the given expression and stores the result in `_res`. + * If the result is not DRANG_EOK, immediately jumps to the cleanup + * section using goto. + * @remarks This macro should only be used within a DRANG_BEGIN_TRY()...DRANG_END_TRY() + * block. The expression should return a DRANG error code. + */ #define DRANG_TRY(expr) \ do { \ _res = (expr); \ @@ -44,6 +87,15 @@ DRANG_API const char *drang_error_str(int err); } \ } while (0) +/** + * @brief Checks a condition and fails with specified error if false. + * @param expr Boolean expression to evaluate. + * @param err Error code to set if the expression is false. + * @details If the expression evaluates to false, sets `_res` to the specified + * error code and jumps to the cleanup section. + * @remarks Use this for validating preconditions, parameter checks, or any + * boolean conditions that should cause the function to fail. + */ #define DRANG_CHECK(expr, err) \ do { \ if (!(expr)) { \ @@ -52,18 +104,52 @@ DRANG_API const char *drang_error_str(int err); } \ } while (0) +/** + * @brief Immediately fails with the specified error code. + * @param err Error code to set before jumping to clean up. + * @details Sets `_res` to the specified error code and immediately jumps + * to the cleanup section without any condition checking. + * @remarks Use this when you need to unconditionally fail and exit the + * current function with a specific error code. + */ #define DRANG_FAIL(err) \ _res = (err); \ goto _drang_cleanup +/** + * @brief Successfully returns a value through an output parameter. + * @param _Out_Ptr_ Pointer to the output parameter. + * @param _Value_ Value to assign to the output parameter. + * @details Sets the output parameter to the specified value, marks the + * operation as successful (DRANG_EOK), and jumps to clean up. + * @remarks Use this macro when you need to return a value through a pointer + * parameter and ensure proper cleanup before function exit. + */ #define DRANG_RETURN_IN(_Out_Ptr_, _Value_) \ _res = DRANG_EOK; \ (*(_Out_Ptr_) = (_Value_)); \ goto _drang_cleanup + +/** + * @brief Successfully completes the operation and jumps to cleanup. + * @details Sets `_res` to DRANG_EOK and jumps to the cleanup section, + * indicating successful completion of the operation. + * @remarks Use this when you need to exit successfully from the middle + * of a function while ensuring proper cleanup is performed. + */ #define DRANG_RETURN() \ _res = DRANG_EOK; \ goto _drang_cleanup +/** + * @brief Checks if a pointer is NULL and fails with specified error. + * @param ptr Pointer to check for NULL. + * @param err Error code to set if the pointer is NULL. + * @details If the pointer is NULL, sets `_res` to the specified error + * code and jumps to the cleanup section. + * @remarks Use this for validating pointer parameters or return values + * from functions that might return NULL on failure. + */ #define DRANG_FAIL_IF_NULL(ptr, err) \ do { \ if ((ptr) == NULL) { \ @@ -72,12 +158,15 @@ DRANG_API const char *drang_error_str(int err); } \ } while (0) -#define DRANG_FAIL_IF_NULL_OOM(ptr) \ - do { \ - if ((ptr) == NULL) { \ - _res = DRANG_ENOMEM; \ - goto _drang_cleanup; \ - } \ - } while (0) +/** + * @brief Checks if a pointer is NULL and fails with out-of-memory error. + * @param ptr Pointer to check for NULL. + * @details If the pointer is NULL, sets `_res` to DRANG_ENOMEM and jumps + * to the cleanup section. This is a convenience macro for memory + * allocation failure checks. + * @remarks Use this specifically after memory allocation operations where + * NULL indicates out-of-memory condition. + */ +#define DRANG_FAIL_IF_NULL_OOM(ptr) DRANG_FAIL_IF_NULL(ptr, DRANG_ENOMEM) DRANG_END_DECLS diff --git a/Source/DrangPlatform/Source/error.c b/Source/DrangPlatform/Source/error.c index 6baec93..437528c 100644 --- a/Source/DrangPlatform/Source/error.c +++ b/Source/DrangPlatform/Source/error.c @@ -10,6 +10,10 @@ const char *drang_error_str(const int err) case DRANG_NOTSUP: return "Operation not supported"; case DRANG_EAGAIN: return "Resource temporarily unavailable"; case DRANG_ENOENT: return "No such file or directory"; + case DRANG_EDEADLK: return "Resource deadlock would occur"; + case DRANG_EPERM: return "Operation not permitted"; + case DRANG_ETIMEDOUT: return "Connection timed out"; + case DRANG_EBUSY: return "Device or resource busy"; default: return "Unknown error"; } }