From 3b14232d439428e1536e1fbe06e9d64a61a275a4 Mon Sep 17 00:00:00 2001 From: Claudius Holeksa Date: Tue, 2 May 2023 17:21:28 +0200 Subject: c++: Changed core for new error features --- forstio/core/buffer.cpp | 10 ++--- forstio/core/error.cpp | 90 +++++++++++++++++++++++++++++--------- forstio/core/error.h | 112 ++++++++++++++++++++++++++++-------------------- 3 files changed, 140 insertions(+), 72 deletions(-) diff --git a/forstio/core/buffer.cpp b/forstio/core/buffer.cpp index 2f1a6b5..ad471d7 100644 --- a/forstio/core/buffer.cpp +++ b/forstio/core/buffer.cpp @@ -13,7 +13,7 @@ error buffer::push(const uint8_t &value) { write() = value; write_advance(1); } else { - return recoverable_error("Buffer too small"); + return make_error(); } return no_error(); } @@ -39,7 +39,7 @@ error buffer::pop(uint8_t &value) { value = read(); read_advance(1); } else { - return recoverable_error("Buffer too small"); + return make_error(); } return no_error(); } @@ -55,7 +55,7 @@ error buffer::pop(uint8_t &buffer, size_t size) { buffer_ptr += segment; } } else { - return recoverable_error("Buffer too small"); + return make_error(); } return no_error(); } @@ -348,7 +348,7 @@ const uint8_t &ring_buffer::write(size_t i) const { error ring_buffer::write_require_length(size_t bytes) { size_t write_remain = write_composite_length(); if (bytes > write_remain) { - return recoverable_error("Buffer too small"); + return make_error(); } return no_error(); } @@ -426,7 +426,7 @@ const uint8_t &array_buffer::write(size_t i) const { error array_buffer::write_require_length(size_t bytes) { size_t write_remain = write_composite_length(); if (bytes > write_remain) { - return recoverable_error("Buffer too small"); + return make_error(); } return no_error(); } diff --git a/forstio/core/error.cpp b/forstio/core/error.cpp index 757e6a8..727ca95 100644 --- a/forstio/core/error.cpp +++ b/forstio/core/error.cpp @@ -1,17 +1,19 @@ #include "error.h" namespace saw { -error::error() : error_{static_cast(0)} {} +error::error(error::code code_, bool is_critical__) + : error_code_{static_cast(code_)}, is_critical_{is_critical__} {} -error::error(const std::string_view &msg, error::code code) - : error_message_{msg}, error_{static_cast(code)} {} - -error::error(std::string &&msg, error::code code) - : error_message_{std::move(msg)}, error_{static_cast(code)} {} +error::error(error::code code_, bool is_critical__, const std::string_view &msg) + : + error_code_{static_cast(code_)} + , is_critical_{is_critical__}, error_message_{msg}{} error::error(error &&error) - : error_message_{std::move(error.error_message_)}, error_{std::move( - error.error_)} {} + : + error_code_{std::move(error.error_code_)} + , is_critical_{std::move(error.is_critical_)} + , error_message_{std::move(error.error_message_)}{} const std::string_view error::message() const { @@ -31,43 +33,89 @@ const std::string_view error::message() const { } bool error::failed() const { - return static_cast>(error_) != 0; + return this->is_error(); } bool error::is_critical() const { - return static_cast>(error_) < 0; + return is_critical_; } bool error::is_recoverable() const { - return static_cast>(error_) > 0; + return !is_critical_; } error error::copy_error() const { - error error; - error.error_ = error_; + auto copy_error_code = error_code_; + error error{copy_error_code, is_critical_}; + try { error.error_message_ = error_message_; } catch (const std::bad_alloc &) { error.error_message_ = std::string_view{"Error while copying Error string. Out of memory"}; } + return error; } -error::code error::id() const { return static_cast(error_); } +error::code error::get_id() const { return error_code_; } + +namespace impl { +error_registry& get_error_registry() { + static own reg = nullptr; + if(!reg){ + reg = heap(); + } -error make_error(const std::string_view &generic, error::code code) { - return error{generic, code}; + assert(reg); + return *reg; +} } -error critical_error(const std::string_view &generic, error::code c) { - return make_error(generic, c); +error no_error(){ + return make_error(); } -error recoverable_error(const std::string_view &generic, error::code c) { - return make_error(generic, c); +namespace impl { +error_or error_registry::search_id(const std::string_view& desc)const{ + /** + * Search the index in the vector + */ + size_t i{}; + size_t info_max_size = std::min(infos.size(), std::numeric_limits::max()); + for(i = 0; i < info_max_size; ++i){ + if(infos.at(i).description == desc){ + break; + } + } + + if(i == info_max_size){ + return make_error(); + } + + return static_cast(i); } -error no_error() { return error{}; } +error_or error_registry::search_or_register_id(const std::string_view& desc, bool is_critical){ + auto err_or_id = search_id(desc); + + if(err_or_id.is_value()){ + return err_or_id.get_value(); + } + + auto& err = err_or_id.get_error(); + + if(err.is_error()){ + size_t new_index = infos.size(); + if(new_index == std::numeric_limits::max()){ + return make_error("Error registry ids are exhausted"); + } + infos.emplace_back(error_info{desc, is_critical}); + return static_cast(new_index); + } + + return std::move(err); +} +} } // namespace saw diff --git a/forstio/core/error.h b/forstio/core/error.h index a8d299b..304b375 100644 --- a/forstio/core/error.h +++ b/forstio/core/error.h @@ -1,5 +1,7 @@ #pragma once +#include +#include #include #include #include @@ -19,13 +21,13 @@ class error { public: using code = uint32_t; private: - std::variant error_message_; code error_code_; + bool is_critical_; + std::variant error_message_; public: - error(); - error(error::code id); - error(error::code id, const std::string_view &msg); + error(error::code id, bool is_critical); + error(error::code id, bool is_critical, const std::string_view &msg); error(error &&error); SAW_FORBID_COPY(error); @@ -44,82 +46,94 @@ public: error copy_error() const; code get_id() const; + + template + bool is_error() const; }; +template +class error_or; + namespace impl { class error_registry { private: struct error_info { + error_info() = delete; + error_info(const std::string_view& d_, bool critical_):description{d_}, is_critical{critical_}{} + std::string_view description; + bool is_critical; }; std::vector infos; public: - error::code search_or_register_id(const std::string_view& desc){ - auto find = std::find_if(infos.begin(), infos.end(), - - ); + error_or search_id(const std::string_view& desc) const; - if( find != find.end() ){ - - } - } + error_or search_or_register_id(const std::string_view& desc, bool is_critical); }; error_registry& get_error_registry(); template error::code get_template_id(){ - static error::code id = 0; + static error::code id = std::numeric_limits::max(); - if(id == 0){ + if(id == std::numeric_limits::max()){ auto& reg = get_error_registry(); - id = reg.search_or_register_id(typename T::description); + + auto err_or_id = reg.search_or_register_id(T::description, T::is_critical); + if(err_or_id.is_error()){ + return std::numeric_limits::max(); + } + + id = err_or_id.get_value(); } return id; } +} template error make_error(const std::string_view& generic){ - auto id = get_template_id(); + error::code id = impl::get_template_id(); - return error{id}; + return error{id, T::is_critical, generic}; } -error make_error(const std::string_view &generic, error::code c); +template error make_error(){ + error::code id = impl::get_template_id(); -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}; - } + return error{id, T::is_critical}; } -error critical_error(const std::string_view &generic, - error::code c = error::code::GenericCritical); +error make_error(error::code code, const std::string_view &generic); -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); +namespace err { +struct no_error { + static constexpr std::string_view description = "No error has occured"; + static constexpr bool is_critical = false; +}; + +struct buffer_exhausted { + static constexpr std::string_view description = "Buffer is too small"; + static constexpr bool is_critical = false; +}; + +struct not_found { + static constexpr std::string_view description = "Not found"; + static constexpr bool is_critical = false; +}; -template -error recoverable_error(const Formatter &formatter, - const std::string_view &generic, - error::code c = error::code::GenericRecoverable) { - return make_error(formatter, c, generic); +struct out_of_memory { + static constexpr std::string_view description = "Out of memory"; + static constexpr bool is_critical = true; +}; } +/** + * Shorthand for no error happened + */ error no_error(); /** @@ -165,17 +179,17 @@ public: return std::holds_alternative(value_or_error_); } - class error &error() { + class error &get_error() { return std::get(value_or_error_); } - const class error &error() const { + const class error &get_error() const { return std::get(value_or_error_); } - fix_void &value() { return std::get>(value_or_error_); } + fix_void &get_value() { return std::get>(value_or_error_); } - const fix_void &value() const { + const fix_void &get_value() const { return std::get>(value_or_error_); } }; @@ -185,4 +199,10 @@ private: error_or() = delete; }; +template +bool error::is_error() const { + + return error_code_ == impl::get_template_id(); +} + } // namespace saw -- cgit v1.2.3