Scanframe Modular Application 0.1.0
Loading...
Searching...
No Matches
dbgutils.h
Go to the documentation of this file.
1
28#pragma once
29#include <cstring>
30#include <iomanip>
31#include <misc/global.h>
32#include <utility>
33
34#if IS_QT
35 #include <QDebug>
36 #include <QString>
37 #include <QtGlobal>
38#endif
39
40// This define should be defined externally in the project or make file.
41#ifndef SF_DEBUG_LEVEL
42 #define SF_DEBUG_LEVEL 1
43#endif
44
45// Coverts the passed type into a name.
46#define SF_RTTI_NAME(self) sf::demangleTypeName(typeid(self).name())
47// Full current class member function name.
48#define SF_RTTI_FUNCTION SF_RTTI_TYPENAME.append("::").append(__FUNCTION__)
49// Define that converts a 'this' pointer to the class type name.
50#define SF_RTTI_TYPENAME SF_RTTI_NAME(*this)
51// Only the filename part of __FILE__.
52#define SF_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
53
54#if IS_QT
55
56 // Converts the passed type into a name.
57 #define SF_Q_RTTI_NAME(self) QString::fromStdString(SF_RTTI_NAME(self))
58 // Define that converts a 'this' pointer to the class type name.
59 #define SF_Q_RTTI_TYPENAME SF_Q_RTTI_NAME(*this)
60
61inline QDebug& operator<<(QDebug& qd, const std::string& ss)
62{
63 return qd << QString::fromStdString(ss);
64}
65
66namespace sf
67{
68
73class _MISC_CLASS MessageHandler
74{
75 public:
79 static void enable(bool enabled = true);
80
81 private:
85 static QtMessageHandler _initial;
86
93 static void _handler(QtMsgType type, const QMessageLogContext& ctx, const QString& msg);
94};
95
96}// namespace sf
97
98#endif
99
100namespace sf
101{
106{
108 dotThrow = 1U << 0U,
110 dotMessageBox = 1U << 1U,
112 dotStdLog = 1U << 2U,
114 dotStdOut = 1U << 3U,
116 dotStdErr = 1U << 4U,
118 dotDebugString = 1U << 5U,
120 dotDebugBreak = 1U << 6U,
122 dotDefault = 1U << 7U
124
130_MISC_FUNC void UserOutputDebugString(unsigned int type, const char* str) noexcept;
131
137_MISC_FUNC void SetDefaultDebugOutput(unsigned int type);
138
143
148
152_MISC_FUNC void printBacktrace(std::ostream& os);
153
159
165
170
175_MISC_FUNC void freeConsole(bool always = false);
176
182_MISC_FUNC std::string demangleTypeName(const char* name);
183
190template<typename T>
191std::string getTypeName(const T ptr)
192{
193 // Only pointer are allowed.
194 static_assert(std::is_pointer_v<T>);
195 // When not null dereference to get the implementation name.
196 if (ptr)
197 return demangleTypeName(typeid(*ptr).name());
198 //
199 return demangleTypeName(typeid(ptr).name());
200}
201
205class notify_exception : public std::exception
206{
207 public:
208 explicit notify_exception(std::string s)
209 : msg(std::move(s))
210 {}
211
212 [[nodiscard]] const char* what() const noexcept override
213 {
214 return msg.c_str();
215 }
216
217 private:
218 std::string msg;
219};
220
224class _MISC_CLASS debug_ostream : public std::ostringstream
225{
226 public:
227 explicit debug_ostream(int type)
228 : std::ostringstream()
229 , _type(type)
230 {}
231
232 ~debug_ostream() override;
233
234 private:
235 int _type;
236};
237
238}// namespace sf
239
240// Defined types of debug output of which combinations are allowed.
241#define DO_DEFAULT sf::dotDefault
242#define DO_COUT sf::dotStdOut
243#define DO_CLOG sf::dotStdLog
244#define DO_CERR sf::dotStdErr
245#define DO_MSGBOX sf::dotMessageBox
246#define DO_DBGSTR sf::dotDebugString
247#define DO_DBGBRK sf::dotDebugBreak
248
249// Class name and file name separator character
250#define SF_CLS_SEP ';'
251
252// clang-format off
253
254#if (SF_DEBUG_LEVEL == 1)
255
256 #define SF_NORM_NOTIFY(f, a) \
257 { \
258 sf::debug_ostream(f) << a; \
259 }
260// Only Clang and GNU have __PRETTY_FUNCTION__ defined.
261 #if defined(__clang__) || defined(__GNUC__)
262 #define SF_FUNC_NOTIFY(f, a) \
263 { \
264 sf::debug_ostream(f) << __PRETTY_FUNCTION__ << ' ' << a; \
265 }
266 #else
267 #define SF_FUNC_NOTIFY(f, a) \
268 { \
269 sf::debug_ostream(f) << __FUNCTION__ << "() " << a; \
270 }
271 #endif
272 #define SF_RTTI_NOTIFY(f, a) \
273 { \
274 sf::debug_ostream(f) << SF_RTTI_TYPENAME << "::" << __FUNCTION__ << SF_CLS_SEP << " " << a; \
275 }
276 #define SF_COND_NORM_NOTIFY(p, f, a) \
277 { \
278 if (p) \
279 { \
280 SF_NORM_NOTIFY(f, a); \
281 } \
282 }
283 #define SF_COND_FUNC_NOTIFY(p, f, a) \
284 { \
285 if (p) \
286 { \
287 SF_FUNC_NOTIFY(f, a); \
288 } \
289 }
290 #define SF_COND_RTTI_NOTIFY(p, f, a) \
291 { \
292 if (p) \
293 { \
294 SF_RTTI_NOTIFY(f, a); \
295 } \
296 }
297 #if IS_QT
298 #define SF_Q_NOTIFY(a) \
299 { \
300 qDebug() << a; \
301 }
302 #endif
303
304#elif (SF_DEBUG_LEVEL == 2)
305
306 #define _NORM_NOTIFY(f, a) \
307 { \
308 sf::debug_ostream(f) << __FUNCTION__ << ' ' << __FILENAME__ << ':' << __LINE__ << '@' << '\t' << a; \
309 }
310// Only Clang and GNU have __PRETTY_FUNCTION__ defined.
311 #if defined(__clang__) || defined(__GNUC__)
312 #define SF_FUNC_NOTIFY(f, a) \
313 { \
314 sf::debug_ostream(f) << __PRETTY_FUNCTION__ << ' ' << __FILENAME__ << ':' << __LINE__ << '@' << '\t' << a; \
315 }
316 #else
317 #define SF_FUNC_NOTIFY(f, a) \
318 { \
319 sf::debug_ostream(f) << __FUNCTION__ << "() " << __FILENAME__ << ':' << __LINE__ << '@' << '\t' << a; \
320 }
321 #endif
322 #define _RTTI_NOTIFY(f, a) \
323 { \
324 sf::debug_ostream(f) << _RTTI_TYPENAME << "::" << __FUNCTION__ << ' ' << SF_CLS_SEP << __FILENAME__ << ':' << __LINE__ << '@' << '\t' << a; \
325 }
326 #define _COND_NORM_NOTIFY(p, f, a) \
327 { \
328 if (p) \
329 { \
330 _NORM_NOTIFY(f, a); \
331 } \
332 }
333 #define _COND_FUNC_NOTIFY(p, f, a) \
334 { \
335 if (p) \
336 { \
337 _FUNC_NOTIFY(f, a); \
338 } \
339 }
340 #define _COND_RTTI_NOTIFY(p, f, a) \
341 { \
342 if (p) \
343 { \
344 _RTTI_NOTIFY(f, a); \
345 } \
346 }
347 #if IS_QT
348 #define SF_Q_NOTIFY(a) \
349 { \
350 qDebug() << a; \
351 }
352 #endif
353
354#else// _DEBUG_LEVEL == 0
355
356 #define _NORM_NOTIFY(f, a) {}
357 #define _FUNC_NOTIFY(f, a) {}
358 #define _RTTI_NOTIFY(f, a) {}
359 #define _COND_NOTIFY(p, f, a) {}
360 #define _COND_FUNC_NOTIFY(p, f, a) {}
361 #define _COND_RTTI_NOTIFY(p, f, a) {}
362 #if IS_QT
363 #define SF_Q_NOTIFY(a) {}
364 #endif
365
366#endif//DEBUG_LEVEL
367
368// clang-format on
std::ostream & operator<<(std::ostream &os, const sf::TimeSpec &ts)
Operator for writing the sf::TimeSpec to an output-stream.
Definition TimeSpec.h:393
Debug output stream.
Definition dbgutils.h:225
debug_ostream(int type)
Definition dbgutils.h:227
~debug_ostream() override
Definition dbgutils.h:206
notify_exception(std::string s)
Definition dbgutils.h:208
const char * what() const noexcept override
Definition dbgutils.h:212
#define _MISC_FUNC
Definition misc/global.h:39
#define _MISC_CLASS
Definition misc/global.h:40
Definition Application.h:10
_MISC_FUNC void debugBreak()
Causes a break when debugging.
_MISC_FUNC bool isDebuggerActive()
Gets the debugger active status.
std::string getTypeName(const T ptr)
Get the demangled type name of the passed pointer type.
Definition dbgutils.h:191
_MISC_FUNC void SetDefaultDebugOutput(unsigned int type)
Set and get function for the type of output when DO_DEFAULT is passed.
_MISC_FUNC bool isDebug()
Gets the debug status.
_MISC_FUNC void printBacktrace(std::ostream &os)
Prints the backtrace to a stream.
_MISC_FUNC std::string getBacktrace()
Prints the backtrace to a stream.
EDebugOutputType
Definition dbgutils.h:106
@ dotStdErr
Definition dbgutils.h:116
@ dotDefault
Definition dbgutils.h:122
@ dotDebugBreak
Definition dbgutils.h:120
@ dotMessageBox
Definition dbgutils.h:110
@ dotStdOut
Definition dbgutils.h:114
@ dotStdLog
Definition dbgutils.h:112
@ dotThrow
Definition dbgutils.h:108
@ dotDebugString
Definition dbgutils.h:118
_MISC_FUNC unsigned int GetDefaultDebugOutput()
Returns the combination of EDebugOutputType which is the default output.
_MISC_FUNC void UserOutputDebugString(unsigned int type, const char *str) noexcept
Allows the passed string to be presented in various ways.
_MISC_FUNC void freeConsole(bool always=false)
Closes the console window.
_MISC_FUNC std::string demangleTypeName(const char *name)
Demangle the passed rtti mangled type name.