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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <stdint.h>
#include <memory>
#include <stdexcept>
#include <string>
#include <fmt/format.h>
namespace frc {
/**
* Runtime error exception.
*/
class RuntimeError : public std::runtime_error {
public:
RuntimeError(int32_t code, std::string&& loc, std::string&& stack,
std::string&& message);
RuntimeError(int32_t code, const char* fileName, int lineNumber,
const char* funcName, std::string&& stack,
std::string&& message);
int32_t code() const noexcept { return m_data->code; }
const char* loc() const noexcept { return m_data->loc.c_str(); }
const char* stack() const noexcept { return m_data->stack.c_str(); }
/**
* Reports error to Driver Station (using HAL_SendError).
*/
void Report() const;
private:
struct Data {
int32_t code;
std::string loc;
std::string stack;
};
std::shared_ptr<Data> m_data;
};
/**
* Gets error message string for an error code.
*/
const char* GetErrorMessage(int32_t* code);
/**
* Reports an error to the driver station (using HAL_SendError).
* Generally the FRC_ReportError wrapper macro should be used instead.
*
* @param[out] status error code
* @param[in] fileName source file name
* @param[in] lineNumber source line number
* @param[in] funcName source function name
* @param[in] format error message format
* @param[in] args error message format args
*/
void ReportErrorV(int32_t status, const char* fileName, int lineNumber,
const char* funcName, fmt::string_view format,
fmt::format_args args);
/**
* Reports an error to the driver station (using HAL_SendError).
* Generally the FRC_ReportError wrapper macro should be used instead.
*
* @param[out] status error code
* @param[in] fileName source file name
* @param[in] lineNumber source line number
* @param[in] funcName source function name
* @param[in] format error message format
* @param[in] args error message format args
*/
template <typename... Args>
inline void ReportError(int32_t status, const char* fileName, int lineNumber,
const char* funcName, fmt::string_view format,
Args&&... args) {
ReportErrorV(status, fileName, lineNumber, funcName, format,
fmt::make_format_args(args...));
}
/**
* Makes a runtime error exception object. This object should be thrown
* by the caller. Generally the FRC_MakeError wrapper macro should be used
* instead.
*
* @param[out] status error code
* @param[in] fileName source file name
* @param[in] lineNumber source line number
* @param[in] funcName source function name
* @param[in] format error message format
* @param[in] args error message format args
* @return runtime error object
*/
[[nodiscard]]
RuntimeError MakeErrorV(int32_t status, const char* fileName, int lineNumber,
const char* funcName, fmt::string_view format,
fmt::format_args args);
template <typename... Args>
[[nodiscard]]
inline RuntimeError MakeError(int32_t status, const char* fileName,
int lineNumber, const char* funcName,
fmt::string_view format, Args&&... args) {
return MakeErrorV(status, fileName, lineNumber, funcName, format,
fmt::make_format_args(args...));
}
namespace err {
#define S(label, offset, message) inline constexpr int label = offset;
#include "frc/WPIErrors.mac"
#undef S
} // namespace err
namespace warn {
#define S(label, offset, message) inline constexpr int label = offset;
#include "frc/WPIWarnings.mac"
#undef S
} // namespace warn
} // namespace frc
// C++20 relaxed the number of arguments to variadics, but Apple Clang's
// warnings haven't caught up yet: https://stackoverflow.com/a/67996331
#ifdef __clang__
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#endif
/**
* Reports an error to the driver station (using HAL_SendError).
*
* @param[out] status error code
* @param[in] format error message format
*/
#define FRC_ReportError(status, format, ...) \
do { \
if ((status) != 0) { \
::frc::ReportError(status, __FILE__, __LINE__, __FUNCTION__, \
format __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
/**
* Reports a warning to the driver station (using HAL_SendError).
*
* @param[in] format error message format
*/
#define FRC_ReportWarning(format, ...) \
do { \
::frc::ReportError(::frc::warn::Warning, __FILE__, __LINE__, __FUNCTION__, \
format __VA_OPT__(, ) __VA_ARGS__); \
} while (0)
/**
* Makes a runtime error exception object. This object should be thrown
* by the caller.
*
* @param[out] status error code
* @param[in] format error message format
* @return runtime error object
*/
#define FRC_MakeError(status, format, ...) \
::frc::MakeError(status, __FILE__, __LINE__, __FUNCTION__, \
format __VA_OPT__(, ) __VA_ARGS__)
/**
* Checks a status code and depending on its value, either throws a
* RuntimeError exception, calls ReportError, or does nothing (if no error).
*
* @param[out] status error code
* @param[in] format error message format
*/
#define FRC_CheckErrorStatus(status, format, ...) \
do { \
if ((status) < 0) { \
throw ::frc::MakeError(status, __FILE__, __LINE__, __FUNCTION__, \
format __VA_OPT__(, ) __VA_ARGS__); \
} else if ((status) > 0) { \
::frc::ReportError(status, __FILE__, __LINE__, __FUNCTION__, \
format __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#define FRC_AssertMessage(condition, format, ...) \
do { \
if (!(condition)) { \
throw ::frc::MakeError(::frc::err::AssertionFailure, __FILE__, __LINE__, \
__FUNCTION__, format __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#define FRC_Assert(condition) FRC_AssertMessage(condition, #condition)