diff --git a/src/common/error.c b/src/common/error.c new file mode 100644 index 0000000..bc48c43 --- /dev/null +++ b/src/common/error.c @@ -0,0 +1,53 @@ +#include "error.h" + +#include +#include +#include + +error_t *const err_errorf_alloc = + &(error_t){.message = "Allocation failed during formatting of another error"}; + +error_t *const err_errorf_length = &(error_t){ + .message = "Formatting of another error failed to determine the error length"}; + +error_t *const err_eof = &(error_t){.message = "Read failed because EOF is reached"}; + +error_t *const err_unknown_read_failure = &(error_t){.message = "Unknown read error"}; + +error_t *const err_allocation_failed = &(error_t){.message = "Memory allocation failed"}; + +error_t *const err_integer_overflow = &(error_t){.message = "Integer overflow"}; + +error_t *const err_invalid_parameters = + &(error_t){.message = "One or more parameters were invalid"}; + +error_t *errorf(const char *fmt, ...) { + error_t *err = calloc(1, sizeof(error_t)); + if (err == nullptr) + return err_errorf_alloc; + + va_list args; + va_list args_count; + va_start(args, fmt); + va_copy(args_count, args); + + int size = vsnprintf(nullptr, 0, fmt, args_count) + 1; + va_end(args_count); + if (size <= 0) { + free(err); + va_end(args); + return err_errorf_length; + } + + err->message = malloc(size); + if (err->message == nullptr) { + free(err); + va_end(args); + return err_errorf_alloc; + } + + vsnprintf(err->message, size, fmt, args); + va_end(args); + err->is_heap_allocated = true; + return err; +} diff --git a/src/common/error.h b/src/common/error.h new file mode 100644 index 0000000..3f5fba4 --- /dev/null +++ b/src/common/error.h @@ -0,0 +1,28 @@ +#ifndef INCLUDE_COMMON_ERROR_H_ +#define INCLUDE_COMMON_ERROR_H_ + +#include + +typedef struct error { + char *message; + bool is_heap_allocated; +} error_t; + +error_t *errorf(const char *fmt, ...); +static inline void error_free(error_t *err) { + if (err == nullptr) + return; + if (!err->is_heap_allocated) + return; + free(err->message); + free(err); +} + +/* Some global errors */ +extern error_t *const err_allocation_failed; +extern error_t *const err_integer_overflow; +extern error_t *const err_invalid_parameters; +extern error_t *const err_eof; +extern error_t *const err_unknown_read_failure; + +#endif // INCLUDE_COMMON_ERROR_H_