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 */
|
||||
#include "Exception.hpp"
|
||||
#include <sstream>
|
||||
#include "ErrorHelpers.hpp"
|
||||
|
||||
/// \defgroup Ensure Ensure
|
||||
/// \brief A set of ensure macros.
|
||||
|
||||
#ifndef NO_ENSURE
|
||||
|
||||
/// @brief Ensures an expression is true. Throws an exception if the assertion fails.
|
||||
/// @ingroup Ensure
|
||||
#define Ensure(expr) \
|
||||
if (!(expr)) { \
|
||||
std::stringstream ss; \
|
||||
ss << "[" << file_name(__FILE__) << ":" << __LINE__ << "] ENSURE FAILED: \""; \
|
||||
ss << #expr << "\""; \
|
||||
throw ArbUt::Exception(ss.str()); \
|
||||
throw ArbUt::__ErrorHelpers::CreateEnsureError(#expr, std::source_location::current()); \
|
||||
}
|
||||
|
||||
/// @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.
|
||||
/// @ingroup Ensure
|
||||
#define EnsureNotNull(value) Ensure((value) != nullptr)
|
||||
|
||||
/// @brief Ensures a range is not null.
|
||||
/// @ingroup Ensure
|
||||
#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
|
||||
#define ARBUTILS_EXCEPTION_HPP
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include "ErrorHelpers.hpp"
|
||||
#if defined(__clang__)
|
||||
#include <experimental/source_location>
|
||||
#else
|
||||
#include <source_location>
|
||||
#endif
|
||||
|
||||
#if !WINDOWS
|
||||
#if PRETTYTRACES
|
||||
|
@ -10,6 +16,22 @@
|
|||
#include "../extern/backward.hpp"
|
||||
#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 {
|
||||
/// @brief Implementation of std::logic_error that gives a stack trace when thrown.
|
||||
class Exception : std::logic_error {
|
||||
|
@ -95,6 +117,17 @@ namespace ArbUt {
|
|||
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:
|
||||
static void AppendNoSourceStack(std::stringstream& ss, const backward::ResolvedTrace& trace,
|
||||
bool include_addr) {
|
||||
|
@ -143,22 +176,8 @@ namespace ArbUt {
|
|||
#define consteval constexpr
|
||||
#endif
|
||||
|
||||
static consteval const char* file_name(const char* path) {
|
||||
const char* file = path;
|
||||
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 THROW(message, ...) \
|
||||
{ ArbUt::Exception::Throw(message, std::source_location::current(), ##__VA_ARGS__); }
|
||||
|
||||
#define NOT_REACHABLE THROW("Not reachable");
|
||||
#define NOT_IMPLEMENTED THROW("Not implemented");
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
using namespace ArbUt;
|
||||
|
||||
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") {
|
||||
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
|
Loading…
Reference in New Issue