feat(utils/error): updated error codes
This commit is contained in:
@@ -76,10 +76,40 @@ namespace serif::utils::errors {
|
||||
INVALID_ELEMENT_ID_ERROR,
|
||||
ELEMENT_NULLPTR_ERROR,
|
||||
|
||||
// Discretization Errors
|
||||
DISCRETIZATION_ERROR = 500,
|
||||
|
||||
//Schema Error
|
||||
SCHEMA_ERROR = 510,
|
||||
INVALID_SCHEMA_ARGUMENTS = 512,
|
||||
|
||||
//As yet uncategorized errors
|
||||
MATRIX_SHAPE_ERROR = 500,
|
||||
MATRIX_SHAPE_ERROR = 600,
|
||||
OUT_OF_RANGE_ERROR,
|
||||
|
||||
// Solver Errors
|
||||
SOLVER_ERROR = 700,
|
||||
//NormalizationErrors
|
||||
NORMALIZATION_ERROR = 730,
|
||||
NORMALIZATION_VECTOR_SIZE_MISMATCH,
|
||||
NORMALIZATION_BUFFER_OVERLAP,
|
||||
|
||||
// Preconditioner Errors
|
||||
PRECONDITIONER_ERROR = 750,
|
||||
PRECONDITIONER_INVALID_OPTIONS,
|
||||
PRECONDITIONER_INVALID_OPERATOR,
|
||||
PRECONDITIONER_SIZE_MISMATCH,
|
||||
PRECONDITIONER_NONFINITE_VALUE,
|
||||
PRECONDITIONER_SINGULAR_OPERATOR,
|
||||
PRECONDITIONER_ILL_CONDITIONED_OPERATOR,
|
||||
PRECONDITIONER_STALE_LINEARIZATION,
|
||||
PRECONDITIONER_INCOMPATIBLE_STRATEGY,
|
||||
PRECONDITIONER_UNPREPARED,
|
||||
PRECONDITIONER_INVALID_CALIBRATION,
|
||||
|
||||
// Equation Errors
|
||||
EQUATION_ERROR = 800,
|
||||
|
||||
// COMPILE TIME FAILURES (>1000)
|
||||
// Type Invariant Failures
|
||||
FAILED_TYPE_INVARIANT = 1000
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
#include <format>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
#include <version>
|
||||
|
||||
#include "serif/utils/misc/terminal/colors.hpp"
|
||||
#include "serif/utils/misc/concepts/exceptions.hpp"
|
||||
@@ -18,13 +20,15 @@
|
||||
// If you want to throw a warning then look at the parallel warnings module and call serif_warning
|
||||
// Note errors cannot be disabled at compile time, warnings can be disabled to a noop at compile time.
|
||||
|
||||
|
||||
namespace serif::utils::errors {
|
||||
template <misc::concepts::IsException ExceptionT, SERiFErrorCode code>
|
||||
void serif_error(const std::string_view message, auto... args) {
|
||||
template <SERiFErrorCode code>
|
||||
std::string format_error_message(const std::string_view message, auto... args) {
|
||||
std::string error_msg;
|
||||
std::string code_name{SERiFErrorCodeTypeToNameMap.at(code)};
|
||||
|
||||
std::ranges::transform(code_name, code_name.begin(), [](const unsigned char c){ return std::toupper(c); });
|
||||
|
||||
if (misc::terminal::supports_ansi(stderr)) {
|
||||
error_msg = std::format("{}{}{}: {}", misc::terminal::a_red, "Error", misc::terminal::a_reset, std::vformat(message, std::make_format_args(args...)));
|
||||
// format error code with color if terminal supports ANSI
|
||||
@@ -34,48 +38,41 @@ namespace serif::utils::errors {
|
||||
// Add error code without color if terminal does not support ANSI
|
||||
error_msg = std::format("{} (code No.: {} [{}])", error_msg, static_cast<std::underlying_type_t<SERiFErrorCode>>(code), code_name);
|
||||
}
|
||||
|
||||
throw ExceptionT(error_msg);
|
||||
return error_msg;
|
||||
}
|
||||
|
||||
template <SERiFErrorCode code, misc::concepts::IsException ExceptionT = std::logic_error>
|
||||
void serif_assert(const bool condition, const std::string_view message, auto... args) {
|
||||
// collapse to a noop if NDEBUG is defined
|
||||
#ifndef NDEBUG
|
||||
constexpr bool is_debug_build = true;
|
||||
#else
|
||||
constexpr bool is_debug_build = false;
|
||||
#endif
|
||||
if constexpr(is_debug_build) {
|
||||
if (!condition) {
|
||||
serif_error<ExceptionT, code>(message, args...);
|
||||
}
|
||||
}
|
||||
template <misc::concepts::IsException ExceptionT, SERiFErrorCode code>
|
||||
void serif_error(const std::string_view message, auto... args) {
|
||||
std::string error_msg = format_error_message<code>(message, args...);
|
||||
throw ExceptionT(error_msg);
|
||||
}
|
||||
|
||||
|
||||
template <auto Message, auto Code>
|
||||
struct serif_error_printer;
|
||||
|
||||
template <SERiFErrorCode code, types::ct_error_string message, bool condition>
|
||||
template <SERiFErrorCode code, bool condition, types::FixedString message>
|
||||
constexpr void serif_assert() {
|
||||
#ifndef NDEBUG
|
||||
constexpr bool is_debug_build = true;
|
||||
if constexpr (!condition) {
|
||||
#if defined(__cpp_static_assert) && __cpp_static_assert >= 202306L /// This is the feature flag for C++26 user defined static_assert messages.
|
||||
static_assert(condition, message);
|
||||
#else
|
||||
constexpr bool is_debug_build = false;
|
||||
[[maybe_unused]] constexpr std::size_t errorKick = sizeof(serif_error_printer<message, code>);
|
||||
#endif
|
||||
|
||||
if constexpr (is_debug_build) {
|
||||
if constexpr (!condition) {
|
||||
// Trigger an intentional error to display the message and code at compile time
|
||||
|
||||
// Note if we move to C++26 we can replace this with a more standard and less convoluted
|
||||
// formated static_assert.
|
||||
[[maybe_unused]] std::size_t error_kick = sizeof(serif_error_printer<message, code>);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <SERiFErrorCode code, misc::concepts::IsException ExceptionT = std::logic_error>
|
||||
void serif_assert(const bool condition, const std::string_view message, auto&&... args) {
|
||||
#ifndef NDEBUG
|
||||
if (!condition) {
|
||||
serif_error<ExceptionT, code>(message, std::forward<decltype(args)>(args)...);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// The difference between serif_assert and serif_ensure is that serif_assert is a noop in release builds, while serif_ensure is always active.
|
||||
// Use an ensure when you want to always check things. Use an assert when you want to check things that are true bugs
|
||||
// and should not manifest in release builds.
|
||||
@@ -86,14 +83,14 @@ namespace serif::utils::errors {
|
||||
}
|
||||
}
|
||||
|
||||
template <SERiFErrorCode code, types::ct_error_string message, bool condition>
|
||||
template <SERiFErrorCode code, bool condition, types::CTString message>
|
||||
constexpr void serif_ensure() {
|
||||
if constexpr (!condition) {
|
||||
// Trigger an intentional error to display the message and code at compile time
|
||||
|
||||
// Note if we move to C++26 we can replace this with a more standard and less convoluted
|
||||
// formated static_assert.
|
||||
[[maybe_unused]] std::size_t error_kick = sizeof(serif_error_printer<message, code>);
|
||||
#if defined(__cpp_static_assert) && __cpp_static_assert >= 202306L /// This is the feature flag for C++26 user defined static_assert messages.
|
||||
static_assert(condition, message);
|
||||
#else
|
||||
[[maybe_unused]] constexpr std::size_t errorKick = sizeof(serif_error_printer<message, code>);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/include/serif/utils/error/nonfinite.hpp
Normal file
15
src/include/serif/utils/error/nonfinite.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace serif::utils::errors {
|
||||
/**
|
||||
* @brief A numerical action produced a nonfinite coefficient, distinguishable from a broken API contract.
|
||||
* Most numerical interfaces report rejection as a value. MFEM operator applications return void,
|
||||
* so their checked caller intercepts this specific bridge while other exceptions propagate.
|
||||
*/
|
||||
class NonFiniteValue final : public std::domain_error {
|
||||
public:
|
||||
using std::domain_error::domain_error;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user