#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 b_error_definition sample_errors[] = { B_ERROR_DEFINITION(SAMPLE_OK, "OK", "Success"), B_ERROR_DEFINITION(SAMPLE_ERR_IO_FAILURE, "IO_FAILURE", "I/O failure"), B_ERROR_DEFINITION_TEMPLATE( SAMPLE_ERR_FILE_READ_FAILED, "FILE_READ_FAILED", "Failed to read file @i[filepath]", B_ERROR_TEMPLATE_PARAM( "filepath", B_ERROR_TEMPLATE_PARAM_STRING, "%s")), }; static const b_error_msg sample_error_msg[] = { B_ERROR_MSG_TEMPLATE( SAMPLE_MSG_A_TEMPLATED_MSG, "A templated message: @e[param1]", B_ERROR_TEMPLATE_PARAM( "param1", B_ERROR_TEMPLATE_PARAM_STRING, "%s")), }; static const char *sample_code_to_string( const struct b_error_vendor *vendor, b_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 b_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 b_result error_return_3(void) { b_result err = b_error_with_string( &sample_vendor, SAMPLE_ERR_IO_FAILURE, "I/O failure while reading file"); b_error_add_submsg_string( err, B_ERROR_SUBMSG_ERROR, "An @e{error} message"); b_error_add_submsg_string( err, B_ERROR_SUBMSG_WARNING, "A @w{warning} message"); b_error_add_submsg_template( err, B_ERROR_SUBMSG_WARNING, SAMPLE_MSG_A_TEMPLATED_MSG, B_ERROR_PARAM("param1", "Hello!")); return err; } static b_result error_return_2(void) { return b_result_propagate(error_return_3()); } static b_result error_return_1(void) { return b_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 b_result some_operation(void) { b_result result = error_return_2(); if (b_result_is_error(result)) { b_result err = b_error_with_template( &sample_vendor, SAMPLE_ERR_FILE_READ_FAILED, B_ERROR_PARAM("filepath", "src/Manifest.json")); b_error_add_submsg_string( err, B_ERROR_SUBMSG_INFO, "An @i{informational} message"); b_error_caused_by_b_status(result, B_ERR_IO_FAILURE); b_result err2 = b_error_caused_by(err, result); return err2; } return B_RESULT_SUCCESS; } int main(void) { b_set_error_report_function(b_enhanced_error_reporter, B_ERROR_REPORT_ALL); test(PARAM("Hello", 1), PARAM("Goodbye", 2)); b_result err; if (B_CATCH(err, some_operation())) { b_throw(err); } b_throw_status(B_ERR_INVALID_ARGUMENT); b_throw_status_string(B_ERR_INVALID_ARGUMENT, "Hello!"); return 0; }