Files
allwpilib/wpilibc/src/main/native/include/frc/Errors.h
2021-05-25 10:04:32 -07:00

177 lines
6.2 KiB
C++

// 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 status error code
* @param fileName source file name
* @param lineNumber source line number
* @param funcName source function name
* @param format error message format
* @param 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 status error code
* @param fileName source file name
* @param lineNumber source line number
* @param funcName source function name
* @param format error message format
* @param args error message format args
*/
template <typename S, typename... Args>
inline void ReportError(int32_t status, const char* fileName, int lineNumber,
const char* funcName, const S& format, Args&&... args) {
ReportErrorV(status, fileName, lineNumber, funcName, format,
fmt::make_args_checked<Args...>(format, 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 status error code
* @param message error message details
* @param fileName source file name
* @param lineNumber source line number
* @param funcName source function name
* @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 S, typename... Args>
[[nodiscard]] inline RuntimeError MakeError(int32_t status,
const char* fileName,
int lineNumber,
const char* funcName,
const S& format, Args&&... args) {
return MakeErrorV(status, fileName, lineNumber, funcName, format,
fmt::make_args_checked<Args...>(format, 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
/**
* Reports an error to the driver station (using HAL_SendError).
*
* @param status error code
* @param format error message format
*/
#define FRC_ReportError(status, format, ...) \
do { \
if ((status) != 0) { \
::frc::ReportError(status, __FILE__, __LINE__, __FUNCTION__, \
FMT_STRING(format), __VA_ARGS__); \
} \
} while (0)
/**
* Makes a runtime error exception object. This object should be thrown
* by the caller.
*
* @param status error code
* @param format error message format
* @return runtime error object
*/
#define FRC_MakeError(status, format, ...) \
::frc::MakeError(status, __FILE__, __LINE__, __FUNCTION__, \
FMT_STRING(format), __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 status error code
* @param format error message format
*/
#define FRC_CheckErrorStatus(status, format, ...) \
do { \
if ((status) < 0) { \
throw ::frc::MakeError(status, __FILE__, __LINE__, __FUNCTION__, \
FMT_STRING(format), __VA_ARGS__); \
} else if ((status) > 0) { \
::frc::ReportError(status, __FILE__, __LINE__, __FUNCTION__, \
FMT_STRING(format), __VA_ARGS__); \
} \
} while (0)
#define FRC_AssertMessage(condition, format, ...) \
do { \
if (!(condition)) { \
throw ::frc::MakeError(err::AssertionFailure, __FILE__, __LINE__, \
__FUNCTION__, FMT_STRING(format), __VA_ARGS__); \
} \
} while (0)
#define FRC_Assert(condition) FRC_AssertMessage(condition, "{}", #condition)