diff --git a/term-test/errors.c b/term-test/errors.c new file mode 100644 index 0000000..efa35e2 --- /dev/null +++ b/term-test/errors.c @@ -0,0 +1,138 @@ +#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; +}