From c4033b8c2028efeb9bac236e6b279bdcd8efec34 Mon Sep 17 00:00:00 2001 From: Claudius Holeksa Date: Tue, 18 Apr 2023 18:34:29 +0200 Subject: First commit to restructure the forstio repo --- forstio/core/error.h | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 forstio/core/error.h (limited to 'forstio/core/error.h') diff --git a/forstio/core/error.h b/forstio/core/error.h new file mode 100644 index 0000000..d8a5ae2 --- /dev/null +++ b/forstio/core/error.h @@ -0,0 +1,149 @@ +#pragma once + +#include +#include +#include + +#include + +#include "common.h" + +namespace saw { +/** + * Utility class for generating errors. Has a base distinction between + * critical and recoverable errors. Additional code ids can be provided to the + * constructor if additional distinctions are necessary. + */ +class error { +public: + enum class code : int16_t { + GenericCritical = -1, + GenericRecoverable = 1, + Disconnected = -99, + Exhausted = -98 + }; + +private: + std::variant error_message_; + code error_; + +public: + error(); + error(const std::string_view &msg, error::code id); + error(std::string &&msg, error::code id); + error(error &&error); + + SAW_FORBID_COPY(error); + + error &operator=(error &&) = default; + + const std::string_view message() const; + bool failed() const; + + bool is_critical() const; + bool is_recoverable() const; + + error copy_error() const; + + code id() const; +}; + +error make_error(const std::string_view &generic, error::code c); + +template +error make_error(const Formatter &formatter, error::code code, + const std::string_view &generic) { + try { + std::string error_msg = formatter(); + return error{std::move(error_msg), code}; + } catch (std::bad_alloc &) { + return error{generic, code}; + } +} + +error critical_error(const std::string_view &generic, + error::code c = error::code::GenericCritical); + +template +error critical_error(const Formatter &formatter, + const std::string_view &generic, + error::code c = error::code::GenericCritical) { + return make_error(formatter, c, generic); +} + +error recoverable_error(const std::string_view &generic, + error::code c = error::code::GenericRecoverable); + +template +error recoverable_error(const Formatter &formatter, + const std::string_view &generic, + error::code c = error::code::GenericRecoverable) { + return make_error(formatter, c, generic); +} + +error no_error(); + +/** + * Exception alternative. Since I code without exceptions this class is + * essentially a kind of exception replacement. + */ +template class error_or; + +class error_or_value { +public: + virtual ~error_or_value() = default; + + template error_or> &as() { + return static_cast> &>(*this); + } + + template const error_or> &as() const { + return static_cast> &>(*this); + } +}; + +template class error_or final : public error_or_value { +private: + std::variant> value_or_error_; + + static_assert(!std::is_same_v, + "Don't use internal private types"); + +public: + error_or() = default; + error_or(const fix_void &value) : value_or_error_{value} {} + + error_or(fix_void &&value) : value_or_error_{std::move(value)} {} + + error_or(const error &error) : value_or_error_{error} {} + error_or(error &&error) : value_or_error_{std::move(error)} {} + + bool is_value() const { + return std::holds_alternative>(value_or_error_); + } + + bool is_error() const { + return std::holds_alternative(value_or_error_); + } + + class error &error() { + return std::get(value_or_error_); + } + + const class error &error() const { + return std::get(value_or_error_); + } + + fix_void &value() { return std::get>(value_or_error_); } + + const fix_void &value() const { + return std::get>(value_or_error_); + } +}; + +template class error_or> { +private: + error_or() = delete; +}; + +} // namespace saw -- cgit v1.2.3