summaryrefslogtreecommitdiff
path: root/src/core/error.cpp
blob: 727ca95fc2839eca7c59b16073d0b34f23930417 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "error.h"

namespace saw {
error::error(error::code code_, bool is_critical__)
	: error_code_{static_cast<error::code>(code_)}, is_critical_{is_critical__} {}

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_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 {

	return std::visit(
		[this](auto &&arg) -> const std::string_view {
			using T = std::decay_t<decltype(arg)>;

			if constexpr (std::is_same_v<T, std::string>) {
				return std::string_view{arg};
			} else if constexpr (std::is_same_v<T, std::string_view>) {
				return arg;
			} else {
				return "Error in class Error. Good luck :)";
			}
		},
		error_message_);
}

bool error::failed() const {
	return this->is_error<err::no_error>();
}

bool error::is_critical() const {
	return is_critical_;
}

bool error::is_recoverable() const {
	return !is_critical_;
}

error error::copy_error() const {
	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::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>();
	}

	assert(reg);
	return *reg;
}
}

error no_error(){
	return make_error<err::no_error>();
}

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_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