summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--forstio/core/buffer.cpp10
-rw-r--r--forstio/core/error.cpp90
-rw-r--r--forstio/core/error.h112
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<err::buffer_exhausted>();
}
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<err::buffer_exhausted>();
}
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<err::buffer_exhausted>();
}
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<err::buffer_exhausted>();
}
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<err::buffer_exhausted>();
}
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<error::code>(0)} {}
+error::error(error::code code_, bool is_critical__)
+ : error_code_{static_cast<error::code>(code_)}, is_critical_{is_critical__} {}
-error::error(const std::string_view &msg, error::code code)
- : error_message_{msg}, error_{static_cast<error::code>(code)} {}
-
-error::error(std::string &&msg, error::code code)
- : error_message_{std::move(msg)}, error_{static_cast<error::code>(code)} {}
+error::error(error::code code_, bool is_critical__, const std::string_view &msg)
+ :
+ error_code_{static_cast<error::code>(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<std::underlying_type_t<error::code>>(error_) != 0;
+ return this->is_error<err::no_error>();
}
bool error::is_critical() const {
- return static_cast<std::underlying_type_t<error::code>>(error_) < 0;
+ return is_critical_;
}
bool error::is_recoverable() const {
- return static_cast<std::underlying_type_t<error::code>>(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::code>(error_); }
+error::code error::get_id() const { return error_code_; }
+
+namespace impl {
+error_registry& get_error_registry() {
+ static own<error_registry> reg = nullptr;
+ if(!reg){
+ reg = heap<error_registry>();
+ }
-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<err::no_error>();
}
-error recoverable_error(const std::string_view &generic, error::code c) {
- return make_error(generic, c);
+namespace impl {
+error_or<error::code> 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<std::size_t>(infos.size(), std::numeric_limits<error::code>::max());
+ for(i = 0; i < info_max_size; ++i){
+ if(infos.at(i).description == desc){
+ break;
+ }
+ }
+
+ if(i == info_max_size){
+ return make_error<err::not_found>();
+ }
+
+ return static_cast<error::code>(i);
}
-error no_error() { return error{}; }
+error_or<error::code> 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<err::not_found>()){
+ size_t new_index = infos.size();
+ if(new_index == std::numeric_limits<error::code>::max()){
+ return make_error<err::out_of_memory>("Error registry ids are exhausted");
+ }
+ infos.emplace_back(error_info{desc, is_critical});
+ return static_cast<error::code>(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 <algorithm>
+#include <limits>
#include <string>
#include <string_view>
#include <variant>
@@ -19,13 +21,13 @@ class error {
public:
using code = uint32_t;
private:
- std::variant<std::string_view, std::string> error_message_;
code error_code_;
+ bool is_critical_;
+ std::variant<std::string_view, std::string> 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<typename T>
+ bool is_error() const;
};
+template<typename T>
+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<error_info> infos;
public:
- error::code search_or_register_id(const std::string_view& desc){
- auto find = std::find_if(infos.begin(), infos.end(),
-
- );
+ error_or<error::code> search_id(const std::string_view& desc) const;
- if( find != find.end() ){
-
- }
- }
+ error_or<error::code> search_or_register_id(const std::string_view& desc, bool is_critical);
};
error_registry& get_error_registry();
template<typename T>
error::code get_template_id(){
- static error::code id = 0;
+ static error::code id = std::numeric_limits<error::code>::max();
- if(id == 0){
+ if(id == std::numeric_limits<error::code>::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<error::code>::max();
+ }
+
+ id = err_or_id.get_value();
}
return id;
}
+}
template<typename T> error make_error(const std::string_view& generic){
- auto id = get_template_id<T>();
+ error::code id = impl::get_template_id<T>();
- return error{id};
+ return error{id, T::is_critical, generic};
}
-error make_error(const std::string_view &generic, error::code c);
+template<typename T> error make_error(){
+ error::code id = impl::get_template_id<T>();
-template <typename Formatter>
-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 <typename Formatter>
-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 <typename Formatter>
-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<class error>(value_or_error_);
}
- class error &error() {
+ class error &get_error() {
return std::get<class error>(value_or_error_);
}
- const class error &error() const {
+ const class error &get_error() const {
return std::get<class error>(value_or_error_);
}
- fix_void<T> &value() { return std::get<fix_void<T>>(value_or_error_); }
+ fix_void<T> &get_value() { return std::get<fix_void<T>>(value_or_error_); }
- const fix_void<T> &value() const {
+ const fix_void<T> &get_value() const {
return std::get<fix_void<T>>(value_or_error_);
}
};
@@ -185,4 +199,10 @@ private:
error_or() = delete;
};
+template<typename T>
+bool error::is_error() const {
+
+ return error_code_ == impl::get_template_id<T>();
+}
+
} // namespace saw