2026-03-16 10:35:43 +00:00
|
|
|
#include <fx/core/error.h>
|
|
|
|
|
#include <fx/term/print.h>
|
2025-07-28 22:23:16 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
};
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
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(
|
2025-07-28 22:23:16 +01:00
|
|
|
SAMPLE_ERR_FILE_READ_FAILED, "FILE_READ_FAILED",
|
|
|
|
|
"Failed to read file @i[filepath]",
|
2026-03-16 10:35:43 +00:00
|
|
|
FX_ERROR_TEMPLATE_PARAM(
|
|
|
|
|
"filepath", FX_ERROR_TEMPLATE_PARAM_STRING, "%s")),
|
2025-07-28 22:23:16 +01:00
|
|
|
};
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
static const fx_error_msg sample_error_msg[] = {
|
|
|
|
|
FX_ERROR_MSG_TEMPLATE(
|
2025-07-28 22:23:16 +01:00
|
|
|
SAMPLE_MSG_A_TEMPLATED_MSG, "A templated message: @e[param1]",
|
2026-03-16 10:35:43 +00:00
|
|
|
FX_ERROR_TEMPLATE_PARAM(
|
|
|
|
|
"param1", FX_ERROR_TEMPLATE_PARAM_STRING, "%s")),
|
2025-07-28 22:23:16 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const char *sample_code_to_string(
|
2026-03-16 10:35:43 +00:00
|
|
|
const struct fx_error_vendor *vendor, fx_error_status_code code)
|
2025-07-28 22:23:16 +01:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
static fx_error_vendor sample_vendor = {
|
2025-07-28 22:23:16 +01:00
|
|
|
.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,
|
|
|
|
|
};
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
static fx_result error_return_3(void)
|
2025-07-28 22:23:16 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_result err = fx_error_with_string(
|
2025-07-28 22:23:16 +01:00
|
|
|
&sample_vendor, SAMPLE_ERR_IO_FAILURE,
|
|
|
|
|
"I/O failure while reading file");
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
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!"));
|
2025-07-28 22:23:16 +01:00
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
static fx_result error_return_2(void)
|
2025-07-28 22:23:16 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
return fx_result_propagate(error_return_3());
|
2025-07-28 22:23:16 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
static fx_result error_return_1(void)
|
2025-07-28 22:23:16 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
return fx_result_propagate(error_return_2());
|
2025-07-28 22:23:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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__, {}})
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
static fx_result some_operation(void)
|
2025-07-28 22:23:16 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_result result = error_return_2();
|
|
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
fx_result err = fx_error_with_template(
|
2025-07-28 22:23:16 +01:00
|
|
|
&sample_vendor, SAMPLE_ERR_FILE_READ_FAILED,
|
2026-03-16 10:35:43 +00:00
|
|
|
FX_ERROR_PARAM("filepath", "src/Manifest.json"));
|
|
|
|
|
fx_error_add_submsg_string(
|
|
|
|
|
err, FX_ERROR_SUBMSG_INFO,
|
2025-07-28 22:23:16 +01:00
|
|
|
"An @i{informational} message");
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_error_caused_by_fx_status(result, FX_ERR_IO_FAILURE);
|
|
|
|
|
fx_result err2 = fx_error_caused_by(err, result);
|
2025-07-28 22:23:16 +01:00
|
|
|
|
|
|
|
|
return err2;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
return FX_RESULT_SUCCESS;
|
2025-07-28 22:23:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_set_error_report_function(fx_enhanced_error_reporter, FX_ERROR_REPORT_ALL);
|
2025-07-28 22:23:16 +01:00
|
|
|
|
|
|
|
|
test(PARAM("Hello", 1), PARAM("Goodbye", 2));
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_result err;
|
|
|
|
|
if (FX_CATCH(err, some_operation())) {
|
|
|
|
|
fx_throw(err);
|
2025-07-28 22:23:16 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_throw_status(FX_ERR_INVALID_ARGUMENT);
|
|
|
|
|
fx_throw_status_string(FX_ERR_INVALID_ARGUMENT, "Hello!");
|
2025-07-28 22:23:16 +01:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|