Thrill  0.1
core.hpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * tlx/die/core.hpp
3  *
4  * Part of tlx - http://panthema.net/tlx
5  *
6  * Copyright (C) 2016-2018 Timo Bingmann <[email protected]>
7  *
8  * All rights reserved. Published under the Boost Software License, Version 1.0
9  ******************************************************************************/
10 
11 #ifndef TLX_DIE_CORE_HEADER
12 #define TLX_DIE_CORE_HEADER
13 
14 #include <cstring>
15 #include <iomanip>
16 #include <sstream>
17 #include <stdexcept>
18 #include <string>
19 
20 namespace tlx {
21 
22 /******************************************************************************/
23 // die macros
24 
25 //! die with message - either throw an exception or die via std::terminate()
26 void die_with_message(const std::string& msg);
27 
28 //! die with message - either throw an exception or die via std::terminate()
29 void die_with_message(const char* msg, const char* file, size_t line);
30 
31 //! die with message - either throw an exception or die via std::terminate()
32 void die_with_message(const std::string& msg, const char* file, size_t line);
33 
34 //! Instead of std::terminate(), throw the output the message via an exception.
35 #define tlx_die_with_sstream(msg) \
36  do { \
37  std::ostringstream oss__; \
38  oss__ << msg << " @ " << __FILE__ << ':' << __LINE__; \
39  ::tlx::die_with_message(oss__.str()); \
40  std::terminate(); /* tell compiler this never returns */ \
41  } while (false)
42 
43 //! Instead of std::terminate(), throw the output the message via an exception.
44 #define tlx_die(msg) \
45  do { \
46  tlx_die_with_sstream("DIE: " << msg); \
47  } while (false)
48 
49 //! Exception thrown by die_with_message() if
50 class DieException : public std::runtime_error
51 {
52 public:
53  explicit DieException(const std::string& message);
54 };
55 
56 //! Switch between dying via std::terminate() and throwing an exception.
57 //! Alternatively define the macro TLX_DIE_WITH_EXCEPTION=1
58 bool set_die_with_exception(bool b);
59 
60 /******************************************************************************/
61 // die_unless() and die_if()
62 
63 //! Check condition X and die miserably if false. Same as assert() except this
64 //! is also active in Release mode.
65 #define tlx_die_unless(X) \
66  do { \
67  if (!(X)) { \
68  ::tlx::die_with_message( \
69  "DIE: Assertion \"" #X "\" failed!", __FILE__, __LINE__); \
70  } \
71  } while (false)
72 
73 //! Check condition X and die miserably if true. Opposite of assert() except
74 //! this is also active in Release mode.
75 #define tlx_die_if(X) \
76  do { \
77  if (X) { \
78  ::tlx::die_with_message( \
79  "DIE: Assertion \"" #X "\" succeeded!", __FILE__, __LINE__); \
80  } \
81  } while (false)
82 
83 //! Check condition X and die miserably if false. Same as tlx_die_unless()
84 //! except the user additionally passes a message.
85 #define tlx_die_verbose_unless(X, msg) \
86  do { \
87  if (!(X)) { \
88  tlx_die_with_sstream( \
89  "DIE: Assertion \"" #X "\" failed!\n" << msg << '\n'); \
90  } \
91  } while (false)
92 
93 //! Check condition X and die miserably if false. Same as tlx_die_if()
94 //! except the user additionally passes a message.
95 #define tlx_die_verbose_if(X, msg) \
96  do { \
97  if ((X)) { \
98  tlx_die_with_sstream( \
99  "DIE: Assertion \"" #X "\" succeeded!\n" << msg << '\n'); \
100  } \
101  } while (false)
102 
103 /******************************************************************************/
104 // die_unequal()
105 
106 //! helper method to compare two values in die_unequal()
107 template <typename TypeA, typename TypeB>
108 inline bool die_equal_compare(TypeA a, TypeB b) {
109  return a == b;
110 }
111 
112 template <>
113 inline bool die_equal_compare(const char* a, const char* b) {
114  // compare string contents
115  return std::strcmp(a, b) == 0;
116 }
117 
118 template <>
119 inline bool die_equal_compare(float a, float b) {
120  // special case for NAN
121  return a != a ? b != b : a == b;
122 }
123 
124 template <>
125 inline bool die_equal_compare(double a, double b) {
126  // special case for NAN
127  return a != a ? b != b : a == b;
128 }
129 
130 //! Check that X == Y or die miserably, but output the values of X and Y for
131 //! better debugging.
132 #define tlx_die_unequal(X, Y) \
133  do { \
134  auto x__ = (X); /* NOLINT */ \
135  auto y__ = (Y); /* NOLINT */ \
136  if (!::tlx::die_equal_compare(x__, y__)) \
137  tlx_die_with_sstream("DIE-UNEQUAL: " #X " != " #Y " : " \
138  "\"" << x__ << "\" != \"" << y__ << "\""); \
139  } while (false)
140 
141 //! Check that X == Y or die miserably, but output the values of X and Y for
142 //! better debugging. Only active if NDEBUG is not defined.
143 #ifdef NDEBUG
144 #define tlx_assert_equal(X, Y)
145 #else
146 #define tlx_assert_equal(X, Y) die_unequal(X, Y)
147 #endif
148 
149 //! Check that X == Y or die miserably, but output the values of X and Y for
150 //! better debugging. Same as tlx_die_unequal() except the user additionally
151 //! pass a message.
152 #define tlx_die_verbose_unequal(X, Y, msg) \
153  do { \
154  auto x__ = (X); /* NOLINT */ \
155  auto y__ = (Y); /* NOLINT */ \
156  if (!::tlx::die_equal_compare(x__, y__)) \
157  tlx_die_with_sstream("DIE-UNEQUAL: " #X " != " #Y " : " \
158  "\"" << x__ << "\" != \"" << y__ << "\"\n" << \
159  msg << '\n'); \
160  } while (false)
161 
162 /******************************************************************************/
163 // die_unequal_eps()
164 
165 //! simple replacement for std::abs
166 template <typename Type>
167 inline Type die_unequal_eps_abs(const Type& t) {
168  return t < 0 ? -t : t;
169 }
170 
171 //! helper method to compare two values in die_unequal_eps()
172 template <typename TypeA, typename TypeB>
173 inline bool die_equal_eps_compare(TypeA x, TypeB y, double eps) {
174  // special case for NAN
175  return x != x ? y != y : die_unequal_eps_abs(x - y) <= eps;
176 }
177 
178 //! Check that ABS(X - Y) <= eps or die miserably, but output the values of X
179 //! and Y for better debugging.
180 #define tlx_die_unequal_eps(X, Y, eps) \
181  do { \
182  auto x__ = (X); /* NOLINT */ \
183  auto y__ = (Y); /* NOLINT */ \
184  if (!::tlx::die_equal_eps_compare(x__, y__, eps)) \
185  tlx_die("DIE-UNEQUAL-EPS: " #X " != " #Y " : " \
186  << std::setprecision(18) \
187  << "\"" << x__ << "\" != \"" << y__ << "\""); \
188  } while (false)
189 
190 //! Check that ABS(X - Y) <= eps or die miserably, but output the values of X
191 //! and Y for better debugging. Same as tlx_die_unequal_eps() except the user
192 //! additionally passes a message.
193 #define tlx_die_verbose_unequal_eps(X, Y, eps, msg) \
194  do { \
195  auto x__ = (X); /* NOLINT */ \
196  auto y__ = (Y); /* NOLINT */ \
197  if (!::tlx::die_equal_eps_compare(x__, y__, eps)) \
198  tlx_die("DIE-UNEQUAL-EPS: " #X " != " #Y " : " \
199  << std::setprecision(18) \
200  << "\"" << x__ << "\" != \"" << y__ << "\"\n" << \
201  msg << '\n'); \
202  } while (false)
203 
204 //! Check that ABS(X - Y) <= 0.000001 or die miserably, but output the values of
205 //! X and Y for better debugging.
206 #define tlx_die_unequal_eps6(X, Y) \
207  die_unequal_eps(X, Y, 1e-6)
208 
209 //! Check that ABS(X - Y) <= 0.000001 or die miserably, but output the values of
210 //! X and Y for better debugging. Same as tlx_die_unequal_eps6() except the user
211 //! additionally passes a message.
212 #define tlx_die_verbose_unequal_eps6(X, Y, msg) \
213  die_verbose_unequal_eps(X, Y, 1e-6, msg)
214 
215 /******************************************************************************/
216 // die_equal()
217 
218 //! Die miserably if X == Y, but first output the values of X and Y for better
219 //! debugging.
220 #define tlx_die_equal(X, Y) \
221  do { \
222  auto x__ = (X); /* NOLINT */ \
223  auto y__ = (Y); /* NOLINT */ \
224  if (::tlx::die_equal_compare(x__, y__)) \
225  tlx_die_with_sstream("DIE-EQUAL: " #X " == " #Y " : " \
226  "\"" << x__ << "\" == \"" << y__ << "\""); \
227  } while (false)
228 
229 //! Die miserably if X == Y, but first output the values of X and Y for better
230 //! debugging. Only active if NDEBUG is not defined.
231 #ifdef NDEBUG
232 #define tlx_assert_unequal(X, Y)
233 #else
234 #define tlx_assert_unequal(X, Y) die_equal(X, Y)
235 #endif
236 
237 //! Die miserably if X == Y, but first output the values of X and Y for better
238 //! debugging. Same as tlx_die_equal() except the user additionally passes a
239 //! message.
240 #define tlx_die_verbose_equal(X, Y, msg) \
241  do { \
242  auto x__ = (X); /* NOLINT */ \
243  auto y__ = (Y); /* NOLINT */ \
244  if (::tlx::die_equal_compare(x__, y__)) \
245  tlx_die_with_sstream("DIE-EQUAL: " #X " == " #Y " : " \
246  "\"" << x__ << "\" == \"" << y__ << "\"\n" << \
247  msg << '\n'); \
248  } while (false)
249 
250 /******************************************************************************/
251 // die_unless_throws()
252 
253 //! Define to check that [code] throws and exception of given type
254 #define tlx_die_unless_throws(code, exception_type) \
255  do { \
256  try { \
257  code; \
258  } \
259  catch (const exception_type&) { \
260  break; \
261  } \
262  ::tlx::die_with_message( \
263  "DIE-UNLESS-THROWS: " #code " - NO EXCEPTION " #exception_type, \
264  __FILE__, __LINE__); \
265  } while (false)
266 
267 } // namespace tlx
268 
269 #endif // !TLX_DIE_CORE_HEADER
270 
271 /******************************************************************************/
Type die_unequal_eps_abs(const Type &t)
simple replacement for std::abs
Definition: core.hpp:167
bool set_die_with_exception(bool b)
Definition: core.cpp:52
bool die_equal_compare(TypeA a, TypeB b)
helper method to compare two values in die_unequal()
Definition: core.hpp:108
Type
VFS object type.
Definition: file_io.hpp:52
DieException(const std::string &message)
Definition: core.cpp:49
bool die_equal_eps_compare(TypeA x, TypeB y, double eps)
helper method to compare two values in die_unequal_eps()
Definition: core.hpp:173
void die_with_message(const std::string &msg)
die with message - either throw an exception or die via std::terminate()
Definition: core.cpp:29
Exception thrown by die_with_message() if.
Definition: core.hpp:50
list x
Definition: gen_data.py:39
std::basic_string< char, std::char_traits< char >, Allocator< char > > string
string with Manager tracking
Definition: allocator.hpp:220