Reworks ensure and throw to not fully depend on macros anymore.
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
parent
ea5c824d34
commit
1be055760a
|
@ -1,19 +1,16 @@
|
||||||
/** @file */
|
/** @file */
|
||||||
#include "Exception.hpp"
|
#include "ErrorHelpers.hpp"
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
/// \defgroup Ensure Ensure
|
/// \defgroup Ensure Ensure
|
||||||
/// \brief A set of ensure macros.
|
/// \brief A set of ensure macros.
|
||||||
|
|
||||||
#ifndef NO_ENSURE
|
#ifndef NO_ENSURE
|
||||||
|
|
||||||
/// @brief Ensures an expression is true. Throws an exception if the assertion fails.
|
/// @brief Ensures an expression is true. Throws an exception if the assertion fails.
|
||||||
/// @ingroup Ensure
|
/// @ingroup Ensure
|
||||||
#define Ensure(expr) \
|
#define Ensure(expr) \
|
||||||
if (!(expr)) { \
|
if (!(expr)) { \
|
||||||
std::stringstream ss; \
|
throw ArbUt::__ErrorHelpers::CreateEnsureError(#expr, std::source_location::current()); \
|
||||||
ss << "[" << file_name(__FILE__) << ":" << __LINE__ << "] ENSURE FAILED: \""; \
|
|
||||||
ss << #expr << "\""; \
|
|
||||||
throw ArbUt::Exception(ss.str()); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Ensures an expression is true for a range. The value in the range can be retrieved using ``item``.
|
/// @brief Ensures an expression is true for a range. The value in the range can be retrieved using ``item``.
|
||||||
|
@ -32,6 +29,7 @@
|
||||||
/// @brief Ensures a pointer is not null.
|
/// @brief Ensures a pointer is not null.
|
||||||
/// @ingroup Ensure
|
/// @ingroup Ensure
|
||||||
#define EnsureNotNull(value) Ensure((value) != nullptr)
|
#define EnsureNotNull(value) Ensure((value) != nullptr)
|
||||||
|
|
||||||
/// @brief Ensures a range is not null.
|
/// @brief Ensures a range is not null.
|
||||||
/// @ingroup Ensure
|
/// @ingroup Ensure
|
||||||
#define EnsureAllNotNull(iterator) EnsureForEach(iterator, item != nullptr)
|
#define EnsureAllNotNull(iterator) EnsureForEach(iterator, item != nullptr)
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "ErrorHelpers.hpp"
|
||||||
|
|
||||||
|
namespace ArbUt {
|
||||||
|
Exception __ErrorHelpers::CreateEnsureError(const char* exp, const std::source_location& location) {
|
||||||
|
std::stringstream error;
|
||||||
|
error << "[" << file_name(location.file_name()) << ":" << location.line() << "] ENSURE FAILED: \"";
|
||||||
|
error << exp << "\"";
|
||||||
|
return Exception(error.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
ArbUt::Exception __ErrorHelpers::CreateThrowError(const char* exp, const std::source_location& location) {
|
||||||
|
std::stringstream error;
|
||||||
|
error << "[" << file_name(location.file_name()) << ":" << location.line() << "] \"";
|
||||||
|
error << exp;
|
||||||
|
error << "\"";
|
||||||
|
return Exception(error.str());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef ARBUTILS_ERRORHELPERS_HPP
|
||||||
|
#define ARBUTILS_ERRORHELPERS_HPP
|
||||||
|
#if defined(__clang__)
|
||||||
|
#include <experimental/source_location>
|
||||||
|
#else
|
||||||
|
#include <source_location>
|
||||||
|
#endif
|
||||||
|
#include <sstream>
|
||||||
|
#include "Exception.hpp"
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
namespace std {
|
||||||
|
using source_location = std::experimental::source_location;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ArbUt {
|
||||||
|
class Exception;
|
||||||
|
|
||||||
|
/// @brief Helper class for multiple error handling
|
||||||
|
class __ErrorHelpers {
|
||||||
|
static constexpr const char* file_name(const char* path) {
|
||||||
|
const char* file = path;
|
||||||
|
while (*path != 0) {
|
||||||
|
if (*path++ == '/') {
|
||||||
|
file = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// @brief Create an error for the Ensure macro
|
||||||
|
static ArbUt::Exception CreateEnsureError(const char* exp, const std::source_location& location);
|
||||||
|
|
||||||
|
/// @brief Create an error for the Throw macro
|
||||||
|
static ArbUt::Exception CreateThrowError(const char* exp, const std::source_location& location);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ARBUTILS_ERRORHELPERS_HPP
|
|
@ -1,7 +1,13 @@
|
||||||
#ifndef ARBUTILS_EXCEPTION_HPP
|
#ifndef ARBUTILS_EXCEPTION_HPP
|
||||||
#define ARBUTILS_EXCEPTION_HPP
|
#define ARBUTILS_EXCEPTION_HPP
|
||||||
#include <string>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include "ErrorHelpers.hpp"
|
||||||
|
#if defined(__clang__)
|
||||||
|
#include <experimental/source_location>
|
||||||
|
#else
|
||||||
|
#include <source_location>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !WINDOWS
|
#if !WINDOWS
|
||||||
#if PRETTYTRACES
|
#if PRETTYTRACES
|
||||||
|
@ -10,6 +16,22 @@
|
||||||
#include "../extern/backward.hpp"
|
#include "../extern/backward.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
namespace std {
|
||||||
|
using source_location = std::experimental::source_location;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static constexpr const char* file_name(const char* path) {
|
||||||
|
const char* file = path;
|
||||||
|
while (*path != 0) {
|
||||||
|
if (*path++ == '/') {
|
||||||
|
file = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ArbUt {
|
namespace ArbUt {
|
||||||
/// @brief Implementation of std::logic_error that gives a stack trace when thrown.
|
/// @brief Implementation of std::logic_error that gives a stack trace when thrown.
|
||||||
class Exception : std::logic_error {
|
class Exception : std::logic_error {
|
||||||
|
@ -95,6 +117,17 @@ namespace ArbUt {
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
static void Throw(const std::string& expression, const std::source_location& location, const Args... args) {
|
||||||
|
std::stringstream error;
|
||||||
|
error << "[" << file_name(location.file_name()) << ":" << location.line() << "] \"";
|
||||||
|
error << expression;
|
||||||
|
using List = int[];
|
||||||
|
(void)List{0, ((void)(error << args), 0)...};
|
||||||
|
error << "\"";
|
||||||
|
throw Exception(error.str());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void AppendNoSourceStack(std::stringstream& ss, const backward::ResolvedTrace& trace,
|
static void AppendNoSourceStack(std::stringstream& ss, const backward::ResolvedTrace& trace,
|
||||||
bool include_addr) {
|
bool include_addr) {
|
||||||
|
@ -143,22 +176,8 @@ namespace ArbUt {
|
||||||
#define consteval constexpr
|
#define consteval constexpr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static consteval const char* file_name(const char* path) {
|
#define THROW(message, ...) \
|
||||||
const char* file = path;
|
{ ArbUt::Exception::Throw(message, std::source_location::current(), ##__VA_ARGS__); }
|
||||||
while (*path != 0) {
|
|
||||||
if (*path++ == '/') {
|
|
||||||
file = path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define THROW(message) \
|
|
||||||
{ \
|
|
||||||
std::stringstream ___ss; \
|
|
||||||
___ss << "[" << file_name(__FILE__) << ":" << __LINE__ << "] " << message; \
|
|
||||||
throw ArbUt::Exception(___ss.str()); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NOT_REACHABLE THROW("Not reachable");
|
#define NOT_REACHABLE THROW("Not reachable");
|
||||||
#define NOT_IMPLEMENTED THROW("Not implemented");
|
#define NOT_IMPLEMENTED THROW("Not implemented");
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
using namespace ArbUt;
|
using namespace ArbUt;
|
||||||
|
|
||||||
static void Thrower() { throw ArbUt::Exception("foobar"); }
|
static void Thrower() { throw ArbUt::Exception("foobar"); }
|
||||||
|
static void ThrowerWithMacro() { THROW("foobar"); }
|
||||||
|
static void ThrowerWithMacroAndParameters([[maybe_unused]] int i) { THROW("foobar", ' ', i); }
|
||||||
|
|
||||||
TEST_CASE("Throw exception get stack trace") {
|
TEST_CASE("Throw exception get stack trace") {
|
||||||
try {
|
try {
|
||||||
|
@ -16,4 +18,20 @@ TEST_CASE("Throw exception get stack trace") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Throw exception with macro, check message") {
|
||||||
|
try {
|
||||||
|
ThrowerWithMacro();
|
||||||
|
} catch (const ArbUt::Exception& e) {
|
||||||
|
REQUIRE_EQ(std::string(e.what()), "[ExceptionTests.cpp:7] \"foobar\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Throw exception with macro and parameters, check message") {
|
||||||
|
try {
|
||||||
|
ThrowerWithMacroAndParameters(684);
|
||||||
|
} catch (const ArbUt::Exception& e) {
|
||||||
|
REQUIRE_EQ(std::string(e.what()), "[ExceptionTests.cpp:8] \"foobar 684\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue