Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/common/error.cpp
4214 views
1
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#include "error.h"
5
#include "small_string.h"
6
#include "string_util.h"
7
8
#include <cstdlib>
9
#include <cstring>
10
#include <cwctype>
11
#include <type_traits>
12
13
#include "fmt/format.h"
14
15
#if defined(_WIN32)
16
#include "windows_headers.h"
17
#endif
18
19
Error::Error() = default;
20
21
Error::Error(const Error& c) = default;
22
23
Error::Error(Error&& e) = default;
24
25
Error::~Error() = default;
26
27
void Error::Clear()
28
{
29
m_description = {};
30
}
31
32
void Error::Clear(Error* errptr)
33
{
34
if (errptr)
35
errptr->Clear();
36
}
37
38
void Error::SetErrno(int err)
39
{
40
SetErrno(std::string_view(), err);
41
}
42
43
void Error::SetErrno(std::string_view prefix, int err)
44
{
45
m_type = Type::Errno;
46
47
#ifdef _MSC_VER
48
char buf[128];
49
if (strerror_s(buf, sizeof(buf), err) == 0)
50
m_description = fmt::format("{}errno {}: {}", prefix, err, buf);
51
else
52
m_description = fmt::format("{}errno {}: <Could not get error message>", prefix, err);
53
#else
54
const char* buf = std::strerror(err);
55
if (buf)
56
m_description = fmt::format("{}errno {}: {}", prefix, err, buf);
57
else
58
m_description = fmt::format("{}errno {}: <Could not get error message>", prefix, err);
59
#endif
60
}
61
62
void Error::SetErrno(Error* errptr, int err)
63
{
64
if (errptr)
65
errptr->SetErrno(err);
66
}
67
68
void Error::SetErrno(Error* errptr, std::string_view prefix, int err)
69
{
70
if (errptr)
71
errptr->SetErrno(prefix, err);
72
}
73
74
void Error::SetString(std::string description)
75
{
76
m_type = Type::User;
77
m_description = std::move(description);
78
}
79
80
void Error::SetStringView(std::string_view description)
81
{
82
m_type = Type::User;
83
m_description = std::string(description);
84
}
85
86
void Error::SetString(Error* errptr, std::string description)
87
{
88
if (errptr)
89
errptr->SetString(std::move(description));
90
}
91
92
void Error::SetStringView(Error* errptr, std::string_view description)
93
{
94
if (errptr)
95
errptr->SetStringView(std::move(description));
96
}
97
98
#ifdef _WIN32
99
100
void Error::SetWin32(unsigned long err)
101
{
102
SetWin32(std::string_view(), err);
103
}
104
105
void Error::SetWin32(std::string_view prefix, unsigned long err)
106
{
107
m_type = Type::Win32;
108
109
WCHAR buf[128];
110
DWORD r = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_USER_DEFAULT, buf,
111
static_cast<DWORD>(std::size(buf)), nullptr);
112
while (r > 0 && std::iswspace(buf[r - 1]))
113
r--;
114
115
if (r > 0)
116
{
117
m_description =
118
fmt::format("{}Win32 Error {}: {}", prefix, err, StringUtil::WideStringToUTF8String(std::wstring_view(buf, r)));
119
}
120
else
121
{
122
m_description = fmt::format("{}Win32 Error {}: <Could not resolve system error ID>", prefix, err);
123
}
124
}
125
126
void Error::SetWin32(Error* errptr, unsigned long err)
127
{
128
if (errptr)
129
errptr->SetWin32(err);
130
}
131
132
void Error::SetWin32(Error* errptr, std::string_view prefix, unsigned long err)
133
{
134
if (errptr)
135
errptr->SetWin32(prefix, err);
136
}
137
138
void Error::SetHResult(long err)
139
{
140
SetHResult(std::string_view(), err);
141
}
142
143
void Error::SetHResult(std::string_view prefix, long err)
144
{
145
m_type = Type::HResult;
146
147
WCHAR buf[128];
148
DWORD r = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_USER_DEFAULT, buf,
149
static_cast<DWORD>(std::size(buf)), nullptr);
150
while (r > 0 && std::iswspace(buf[r - 1]))
151
r--;
152
153
if (r > 0)
154
{
155
m_description = fmt::format("{}HRESULT {:08X}: {}", prefix, static_cast<unsigned>(err),
156
StringUtil::WideStringToUTF8String(std::wstring_view(buf, r)));
157
}
158
else
159
{
160
m_description = fmt::format("{}HRESULT {:08X}: <Could not resolve system error ID>", prefix, err);
161
}
162
}
163
164
void Error::SetHResult(Error* errptr, long err)
165
{
166
if (errptr)
167
errptr->SetHResult(err);
168
}
169
170
void Error::SetHResult(Error* errptr, std::string_view prefix, long err)
171
{
172
if (errptr)
173
errptr->SetHResult(prefix, err);
174
}
175
176
#endif
177
178
void Error::SetSocket(int err)
179
{
180
SetSocket(std::string_view(), err);
181
}
182
183
void Error::SetSocket(std::string_view prefix, int err)
184
{
185
// Socket errors are win32 errors on windows
186
#ifdef _WIN32
187
SetWin32(prefix, err);
188
#else
189
SetErrno(prefix, err);
190
#endif
191
m_type = Type::Socket;
192
}
193
194
void Error::SetSocket(Error* errptr, int err)
195
{
196
if (errptr)
197
errptr->SetSocket(err);
198
}
199
200
void Error::SetSocket(Error* errptr, std::string_view prefix, int err)
201
{
202
if (errptr)
203
errptr->SetSocket(prefix, err);
204
}
205
206
Error Error::CreateNone()
207
{
208
return Error();
209
}
210
211
Error Error::CreateErrno(int err)
212
{
213
Error ret;
214
ret.SetErrno(err);
215
return ret;
216
}
217
218
Error Error::CreateSocket(int err)
219
{
220
Error ret;
221
ret.SetSocket(err);
222
return ret;
223
}
224
225
Error Error::CreateString(std::string description)
226
{
227
Error ret;
228
ret.SetString(std::move(description));
229
return ret;
230
}
231
232
#ifdef _WIN32
233
Error Error::CreateWin32(unsigned long err)
234
{
235
Error ret;
236
ret.SetWin32(err);
237
return ret;
238
}
239
240
Error Error::CreateHResult(long err)
241
{
242
Error ret;
243
ret.SetHResult(err);
244
return ret;
245
}
246
247
#endif
248
249
void Error::AddPrefix(std::string_view prefix)
250
{
251
m_description.insert(0, prefix);
252
}
253
254
void Error::AddSuffix(std::string_view suffix)
255
{
256
m_description.append(suffix);
257
}
258
259
void Error::SetStringFmtArgs(fmt::string_view fmt, fmt::format_args args)
260
{
261
m_type = Type::User;
262
m_description = fmt::vformat(fmt, std::move(args));
263
}
264
265
void Error::AddPrefixFmtArgs(fmt::string_view fmt, fmt::format_args args)
266
{
267
SmallString str;
268
str.vformat(fmt, std::move(args));
269
AddPrefix(str.view());
270
}
271
272
void Error::AddSuffixFmtArgs(fmt::string_view fmt, fmt::format_args args)
273
{
274
SmallString str;
275
str.vformat(fmt, std::move(args));
276
AddSuffix(str.view());
277
}
278
279
void Error::AddPrefix(Error* errptr, std::string_view prefix)
280
{
281
if (errptr)
282
errptr->AddPrefix(prefix);
283
}
284
285
void Error::AddSuffix(Error* errptr, std::string_view prefix)
286
{
287
if (errptr)
288
errptr->AddSuffix(prefix);
289
}
290
291
Error& Error::operator=(const Error& e) = default;
292
293
Error& Error::operator=(Error&& e) = default;
294
295
bool Error::operator==(const Error& e) const
296
{
297
return (m_type == e.m_type && m_description == e.m_description);
298
}
299
300
bool Error::operator!=(const Error& e) const
301
{
302
return (m_type != e.m_type || m_description != e.m_description);
303
}
304