HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
error_info.hpp
1// Copyright Take Vos 2020.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#ifndef ERROR_INFO_HPP
6#define ERROR_INFO_HPP
7
8#pragma once
9
10#include "source_location.hpp"
11#include "tag.hpp"
12#include "concepts.hpp"
13#include "check.hpp"
14#include <cstdint>
15#include <string>
16#include <type_traits>
17#include <optional>
18
19namespace tt {
20
23class URL;
24
27class parse_location;
28
29namespace detail {
30
32 uint64_t version;
33
36 [[nodiscard]] virtual std::string string() noexcept = 0;
37};
38
39template<basic_fixed_string Tag, typename ValueType>
41 using value_type = ValueType;
42
43 std::optional<value_type> value;
44
45 [[nodiscard]] std::string string() noexcept override
46 {
47 using std::to_string;
48 using tt::to_string;
49
50 if constexpr (to_stringable<value_type>) {
51 return fmt::format("{}={}", Tag, to_string(*value));
52 } else {
53 return fmt::format("{}={}", Tag, *value);
54 }
55 }
56};
57
58}
59
82public:
87 error_info(source_location location) noexcept
88 {
89 ++version;
90 tt_axiom(state == state::closed);
91 tt_axiom(version != 0);
92
93 state = state::writing;
94 set<"source_location">(location);
95 }
96
104 error_info(bool reopen) noexcept
105 {
106 tt_axiom(reopen == true);
107 if (state == state::closed) {
108 // Start a new transaction if it wasn't already opened.
109 // This may happen on a catch statement from a traditional exception.
110 ++version;
111
112 } else {
113 tt_axiom(state == state::reading);
114 }
115
116 tt_axiom(version != 0);
117
118 state = state::writing;
119 }
120
122 {
123 tt_axiom(state == state::writing);
124 tt_axiom(version != 0);
125
126 state = state::reading;
127 }
128
129 error_info(error_info &&rhs) noexcept = delete;
130 error_info &operator=(error_info &&rhs) noexcept = delete;
131 error_info(error_info const &rhs) = delete;
132 error_info &operator=(error_info const &rhs) = delete;
133
143 template<basic_fixed_string Tag, typename Arg>
144 error_info &set(Arg &&value) noexcept
145 {
146 tt_axiom(state == state::writing);
147 tt_axiom(version != 0);
148
149 auto &e = entry<Tag, std::remove_cvref_t<Arg>>;
150 if (e.version == 0) {
151 // Track this entry from now on, so that information on all error_info
152 // can be listed dynamically.
153 [[unlikely]] register_entry(e);
154 }
155
156 e.version = version;
157 e.value = std::forward<Arg>(value);
158 return *this;
159 }
160
167 static void close() noexcept
168 {
169 tt_axiom(state == state::closed || state == state::reading);
170
171 state = state::closed;
172 }
173
184 template<typename ValueType, basic_fixed_string Tag>
185 static std::optional<ValueType> pop() noexcept
186 {
187 close();
188 tt_axiom(state == state::closed);
189
190 auto &e = entry<Tag,ValueType>;
191 if (version != 0 && e.version == version) {
192 return std::exchange(e.value, {});
193 } else {
194 return {};
195 }
196 }
197
206 template<typename ValueType, basic_fixed_string Tag>
207 static std::optional<ValueType> peek() noexcept
208 {
209 auto &e = entry<Tag,ValueType>;
210 if (version != 0 && e.version == version) {
211 return e.value;
212 } else {
213 return {};
214 }
215 }
216
219 static std::string string() noexcept
220 {
221 std::string r;
222
223 for (auto e: entries) {
224 if (version != 0 && e->version == version) {
225 if (!r.empty()) {
226 r += ", ";
227 }
228
229 r += e->string();
230 }
231 }
232 return r;
233 }
234
235private:
236 enum class state {
237 closed,
238 writing,
239 reading
240 };
241
244 inline static thread_local uint64_t version;
245
248 inline static thread_local state state;
249
252 template<basic_fixed_string Tag, typename ValueType>
253 inline static thread_local detail::error_info_entry<Tag, ValueType> entry;
254
258 inline static thread_local std::vector<detail::error_info_entry_base *> entries;
259
260 tt_no_inline static void register_entry(detail::error_info_entry_base &e) noexcept
261 {
262 entries.push_back(&e);
263 }
264};
265
269[[nodiscard]] inline std::string to_string(std::exception const &e, bool close=true) noexcept
270{
271 if (close) {
273 }
274 return fmt::format("{}: {}: {}", typeid(e).name(), e.what(), error_info::string());
275}
276
277} // namespace tt
278
279#define tt_error_info() tt::error_info(tt_source_location_current())
280
281#endif
Definition error_info.hpp:31
virtual std::string string() noexcept=0
Get a string representation of the tag and value of this entry.
Definition error_info.hpp:40
std::string string() noexcept override
Get a string representation of the tag and value of this entry.
Definition error_info.hpp:45
Error information passed alongside an error code or exception.
Definition error_info.hpp:81
error_info(source_location location) noexcept
Open an error info transaction.
Definition error_info.hpp:87
static void close() noexcept
Close the current transaction.
Definition error_info.hpp:167
static std::optional< ValueType > peek() noexcept
Non-destructive read data from the current transaction.
Definition error_info.hpp:207
static std::optional< ValueType > pop() noexcept
Destructive read data from the current transaction.
Definition error_info.hpp:185
error_info & set(Arg &&value) noexcept
Set an information for a given tag.
Definition error_info.hpp:144
error_info(bool reopen) noexcept
Reopen a error info transaction.
Definition error_info.hpp:104
static std::string string() noexcept
Return the list of entries with their current set value.
Definition error_info.hpp:219
example: ``` template<tt::basic_fixed_string Foo> class A { auto bar() { return std::string{Foo}; } }...
Definition fixed_string.hpp:29
Definition source_location.hpp:10
Definition version.hpp:11
Definition concepts.hpp:51
T empty(T... args)
T push_back(T... args)
T to_string(T... args)
T what(T... args)