Gorgon Game Engine
Assert.h
Go to the documentation of this file.
1 #pragma once
2 
3 #pragma warning(push)
4 #pragma warning(disable:4297)
5 
6 #include <typeinfo>
7 
8 #include "../String.h"
9 #include "../OS.h"
10 #include "../Utils/Console.h"
11 #include "Compiler.h"
12 
13 namespace Gorgon {
14  namespace Utils {
15 
17  class AssertationException : public std::runtime_error {
18  public:
19  //using std::runtime_error::runtime_error;
20 
21  explicit AssertationException(const std::string &what) : std::runtime_error(what) { }
22  };
23 
25  class CrashHandler {
26  template<class T_>
27  typename std::enable_if<String::CanBeStringified<T_>::Value, std::string>::type
28  fromhelper(const T_ &t) {
29  return String::From(t);
30  }
31 
32  template<class T_>
33  typename std::enable_if<!String::CanBeStringified<T_>::Value, std::string>::type
34  fromhelper(const T_ &t) {
35  return "??";
36  }
37  public:
38  static struct alltag {} AllTag;
39  static struct dumponlytag {} DumpOnlyTag;
40 
41  CrashHandler(const std::string &expression, const std::string &message, int skip=1,
42  int depth=4, bool se=false, bool so=false) :
43  original(expression), message(message), skip(skip), depth(depth),
44  show_expanded(se), show_original(so)
45  {
46  }
47  CrashHandler(alltag, const std::string &expression, const std::string &message, int skip=1,
48  int depth=4, bool se=true, bool so=true) :
49  original(expression), message(message), skip(skip), depth(depth),
50  show_expanded(se), show_original(so)
51  {
52  }
53  CrashHandler(dumponlytag, const std::string &expression, const std::string &message, int skip=1,
54  int depth=4, bool se=false, bool so=false) :
55  original(expression), message(message), skip(skip), depth(depth),
56  show_expanded(se), show_original(so), dumponly(true)
57  {
58  }
59 
60 
61  ~CrashHandler() {
62  auto console = Utils::StdConsole();
63  console.SetColor(console.Red);
64  console.SetBold();
65 
66  std::cout<<"Assertation failed: ";
67  console.SetColor(console.Default);
68  std::cout<<message<<std::endl;
69  console.Reset();
70 
71  if(show_original) {
72  std::cout<<" "<<original;
73  console.SetColor(console.Red);
74  std::cout<<" evaluates to false"<<std::endl;
75  console.Reset();
76  }
77 
78  if(show_expanded) {
79  console.SetColor(console.Green);
80  std::cout<<" "<<expanded;
81  console.SetColor(console.Red);
82  std::cout<<" ==> FALSE"<<std::endl;
83  console.Reset();
84  }
85 
86  Backtrace();
87 
88  console.Reset();
89  if(!dumponly) {
90 #ifdef TEST
91 #pragma GCC diagnostic push
92 #pragma GCC diagnostic ignored "-Wterminate"
93  throw AssertationException(message);
94 #pragma GCC diagnostic pop
95 #else
96  exit(1);
97 #endif
98  }
99  }
100 
102 #define gorgon_makeoperator(op) \
103  template<class T_> \
104  CrashHandler &operator op(const T_ &arg) { \
105  return *this; \
106  }
107 // expanded += " " #op " " + fromhelper<T_>(arg); \
108 
109  // traps right hand side
110  template<class T_>
111  CrashHandler &operator <(const T_ &arg) {
112 // if(expanded=="") {
113 // expanded = fromhelper<T_>(arg);
114 // }
115 // else {
116 // expanded+=" < " + fromhelper<T_>(arg);
117 // }
118 
119  return *this;
120  }
121 
122  void Backtrace();
123 
124  gorgon_makeoperator(==)
125  gorgon_makeoperator(!=)
126  gorgon_makeoperator(>)
127  gorgon_makeoperator(>=)
128  gorgon_makeoperator(<=)
129  gorgon_makeoperator(||)
130  gorgon_makeoperator(&&)
131 
132 #undef gorgon_makeoperator
133 
134  protected:
135  std::string original;
136  std::string expanded;
137  std::string message;
138 
139  int skip;
140  int depth;
141 
142  bool show_original;
143  bool show_expanded;
144 
145  bool dumponly=false;
146  };
148 
149 #ifdef NDEBUG
150  #define ASSERT(...)
151  #define ASSERT_ALL(...)
152  #define ASSERT_DUMP(...)
153 #else
154 
161  #define ASSERT(expression, message, ...) do { if(!bool(expression)) { \
162  auto temp = Gorgon::Utils::CrashHandler(#expression, message, ##__VA_ARGS__); } } while(0)
163 
171  #define ASSERT_ALL(expression, message, ...) do { if(!bool(expression)) { \
172  auto temp = Gorgon::Utils::CrashHandler(Gorgon::Utils::CrashHandler::AllTag, #expression, message, ##__VA_ARGS__); } } while(0)
173 
182  #define ASSERT_DUMP(expression, message, ...) do { if(!bool(expression)) { \
183  auto temp = Gorgon::Utils::CrashHandler(Gorgon::Utils::CrashHandler::DumpOnlyTag,#expression, message, ##__VA_ARGS__); } } while(0)
184 
185 # endif
186 
187  [[noreturn]] inline void NotImplemented (const std::string &what = "This feature") {
188  ASSERT(false, what+" is not implemented.", 0, 8);
189  throw 0;
190  }
191 
192  [[noreturn]] inline void ASSERT_FALSE(const std::string &message, int skip = 1, int depth = 4) {
193  ASSERT(false, message, skip, depth);
194  throw 0;
195  }
196  }
197 }
198 #pragma warning(pop)
Gorgon::String::From
std::enable_if< decltype(gorgon__enum_tr_loc(T_()))::isupgradedenum, std::string >::type From(const T_ &e)
Definition: Enum.h:303
Gorgon::Utils::ASSERT_FALSE
void ASSERT_FALSE(const std::string &message, int skip=1, int depth=4)
Definition: Assert.h:192
Gorgon::Utils::AssertationException::AssertationException
AssertationException(const std::string &what)
Definition: Assert.h:21
Gorgon
Root namespace for Gorgon Game Engine.
Definition: Any.h:19
Gorgon::Utils::AssertationException
Only works when TEST is defined.
Definition: Assert.h:17
ASSERT
#define ASSERT(expression, message,...)
Replaces regular assert to allow messages and backtrace.
Definition: Assert.h:161
Gorgon::Utils::NotImplemented
void NotImplemented(const std::string &what="This feature")
Definition: Assert.h:187
Gorgon::Geometry::operator<
bool operator<(PointList< P_ > &left, const PointList< P_ > &right)
Comparison: this operation is expensive: O(n).
Definition: PointList.h:361