#include #include #include enum sample_code { SAMPLE_OK = 0, SAMPLE_ERR_IO_FAILURE, SAMPLE_ERR_FILE_READ_FAILED, }; enum sample_msg { SAMPLE_MSG_SUCCESS = 0, SAMPLE_MSG_A_TEMPLATED_MSG, }; static const fx_error_definition sample_errors[] = { FX_ERROR_DEFINITION(SAMPLE_OK, "OK", "Success"), FX_ERROR_DEFINITION(SAMPLE_ERR_IO_FAILURE, "IO_FAILURE", "I/O failure"), FX_ERROR_DEFINITION_TEMPLATE( SAMPLE_ERR_FILE_READ_FAILED, "FILE_READ_FAILED", "Failed to read file @i[filepath]", FX_ERROR_TEMPLATE_PARAM( "filepath", FX_ERROR_TEMPLATE_PARAM_STRING, "%s")), }; static const fx_error_msg sample_error_msg[] = { FX_ERROR_MSG_TEMPLATE( SAMPLE_MSG_A_TEMPLATED_MSG, "A templated message: @e[param1]", FX_ERROR_TEMPLATE_PARAM( "param1", FX_ERROR_TEMPLATE_PARAM_STRING, "%s")), }; static const char *sample_code_to_string( const struct fx_error_vendor *vendor, fx_error_status_code code) { switch (code) { case SAMPLE_OK: return "OK"; case SAMPLE_ERR_IO_FAILURE: return "IO_FAILURE"; case SAMPLE_ERR_FILE_READ_FAILED: return "FILE_READ_FAILED"; default: return NULL; } } static fx_error_vendor sample_vendor = { .v_name = "Sample", .v_error_definitions = sample_errors, .v_error_definitions_length = sizeof sample_errors, .v_msg = sample_error_msg, .v_msg_length = sizeof sample_error_msg, }; static fx_result error_return_3(void) { fx_result err = fx_error_with_string( &sample_vendor, SAMPLE_ERR_IO_FAILURE, "I/O failure while reading file"); fx_error_add_submsg_string( err, FX_ERROR_SUBMSG_ERROR, "An @e{error} message"); fx_error_add_submsg_string( err, FX_ERROR_SUBMSG_WARNING, "A @w{warning} message"); fx_error_add_submsg_template( err, FX_ERROR_SUBMSG_WARNING, SAMPLE_MSG_A_TEMPLATED_MSG, FX_ERROR_PARAM("param1", "Hello!")); return err; } static fx_result error_return_2(void) { return fx_result_propagate(error_return_3()); } static fx_result error_return_1(void) { return fx_result_propagate(error_return_2()); } struct param { const char *name; int value; }; #define PARAM(n, v) \ (struct param) \ { \ .name = (n), .value = (v) \ } static void __test(struct param params[]) { for (size_t i = 0; params[i].name; i++) { printf("%s = %d\n", params[i].name, params[i].value); } } #define test(...) __test((struct param[]) {__VA_ARGS__, {}}) static fx_result some_operation(void) { fx_result result = error_return_2(); if (fx_result_is_error(result)) { fx_result err = fx_error_with_template( &sample_vendor, SAMPLE_ERR_FILE_READ_FAILED, FX_ERROR_PARAM("filepath", "src/Manifest.json")); fx_error_add_submsg_string( err, FX_ERROR_SUBMSG_INFO, "An @i{informational} message"); fx_error_caused_by_fx_status(result, FX_ERR_IO_FAILURE); fx_result err2 = fx_error_caused_by(err, result); return err2; } return FX_RESULT_SUCCESS; } int main(void) { fx_set_error_report_function(fx_enhanced_error_reporter, FX_ERROR_REPORT_ALL); test(PARAM("Hello", 1), PARAM("Goodbye", 2)); fx_result err; if (FX_CATCH(err, some_operation())) { fx_throw(err); } fx_throw_status(FX_ERR_INVALID_ARGUMENT); fx_throw_status_string(FX_ERR_INVALID_ARGUMENT, "Hello!"); return 0; }