1 #ifndef MBDebug_HeaderFile
\r
2 #define MBDebug_HeaderFile
\r
4 //---------------------------------------------------------------
\r
5 // Usage of the logging facilities:
\r
7 // (1) At the beginning of each class file to be debugged, there
\r
8 // should be a static string variable defined with the name
\r
9 // of the class. Then, include the "MBDebug.h" header file.
\r
11 // //---------------------------------------------------------
\r
12 // #define USE_DEBUG
\r
13 // //#define MB_IGNORE_QT
\r
14 // //#define MB_FULL_DUMP
\r
15 // #define MBCLASSNAME "ClassName"
\r
16 // #include "MBDebug.h"
\r
17 // // <-- insert includes for addtional debug headers here!
\r
18 // //---------------------------------------------------------
\r
20 // (2) At the beginning of each class method, call the DBG_FUN
\r
23 // int ClassName::MyMethod(int x)
\r
29 // NOTE: For static methods, call the DBG_FUNC() macro!!
\r
30 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\r
31 // This debugging/logging class is a "header-only" solution and
\r
32 // does NOT require any additional implementation (.cpp) file!
\r
33 //---------------------------------------------------------------
\r
45 #ifndef MB_IGNORE_QT
\r
47 # include <QStringList>
\r
50 static std::mutex mtx;
\r
52 //---------------------------------------------------------------
\r
53 // Set the debug flags dependent on the preprocessor definitions
\r
54 //---------------------------------------------------------------
\r
56 # define MBS_DEBUG_FLAG MBDebug::DF_DEBUG
\r
58 # define MBS_DEBUG_FLAG 0
\r
61 #define MBS_DBG_FLAGS (MBS_DEBUG_FLAG)
\r
64 //---------------------------------------------------------------
\r
65 // Define the global debug macros
\r
66 //---------------------------------------------------------------
\r
67 #define DLOG MBDebug::LogPrint()
\r
68 #define RETURN(var) { RET(var); return (var); }
\r
72 # define DBG_FUN() MBDebug _dbg(MBCLASSNAME, __FUNCTION__, MBS_DBG_FLAGS, (void*)this)
\r
73 # define DBG_FUNC() MBDebug _dbg(MBCLASSNAME, __FUNCTION__, MBS_DBG_FLAGS)
\r
74 # define DBG_FUNB(blk) MBDebug _dbg(MBCLASSNAME, blk, MBS_DBG_FLAGS)
\r
75 # define MSGEL(txt) MBDebug::LogPrint() << ":" << txt << std::endl
\r
76 # define PRINT(txt) MBDebug::LogPrint() << txt
\r
77 # define SHOW2(var,typ) do { PRINT(std::this_thread::get_id()); DumpVar(#var,(typ)(var)); } while (0)
\r
78 # define SHOW(var) do { PRINT(std::this_thread::get_id()); DumpVar(#var,var); } while (0)
\r
79 # define ARG(var) do { PRINT(std::this_thread::get_id() << ":in:"); DumpVar(#var,var); } while (0)
\r
80 # define ARG2(var,typ) do { PRINT(std::this_thread::get_id() << ":in:"); DumpVar(#var,(typ)(var)); } while (0)
\r
81 # define RET(var) do { PRINT(std::this_thread::get_id() << ":out:"); DumpVar(#var,var); } while (0)
\r
82 # define MSG(txt) MBDebug::LogPrint() << std::this_thread::get_id() << ":" << txt
\r
84 #else /*!USE_DEBUG*/
\r
88 # define DBG_FUNB(blk)
\r
91 # define SHOW2(var,typ)
\r
94 # define ARG2(var,typ)
\r
98 #endif /*USE_DEBUG*/
\r
101 //---------------------------------------------------------------
\r
102 // Declare the debugging and profiling class
\r
103 //---------------------------------------------------------------
\r
108 DF_NONE = 0x00, // no debug
\r
109 DF_DEBUG = 0x01 // debug a function
\r
112 MBDebug(const char* aClassName, const char* aFuncName, const short aFlag, void* aThis=NULL)
\r
113 :mClassName(aClassName),mFuncName(aFuncName),mThis(aThis),mFlags((unsigned char)aFlag)
\r
115 if (mFlags & (DF_DEBUG))
\r
117 std::lock_guard<std::mutex> lck(mtx);
\r
118 std::cout << std::this_thread::get_id() << ":{ENTER: " << mClassName + "::" + mFuncName;
\r
119 if (mThis) std::cout << "(this=" << mThis << ")";
\r
120 std::cout << std::endl;
\r
125 if (mFlags & (DF_DEBUG))
\r
127 std::lock_guard<std::mutex> lck(mtx);
\r
128 std::cout << std::this_thread::get_id() << ":}LEAVE: " << mClassName << "::" << mFuncName << std::endl;
\r
132 // Log file output management
\r
133 static std::ostream& LogPrint() { return std::cout; }
\r
136 std::string mClassName; // Name of class to be debugged
\r
137 std::string mFuncName; // Name of function to be debugged
\r
138 void* mThis; // The "this" pointer to the class being debugged
\r
139 unsigned char mFlags; // Debug mode flags
\r
144 #define YesNo(b) (b ? "Yes" : "No")
\r
148 inline std::string w2s(std::wstring ws)
\r
150 using convert_typeX = std::codecvt_utf8<wchar_t>;
\r
151 std::wstring_convert<convert_typeX, wchar_t> converterX;
\r
152 return(converterX.to_bytes(ws));
\r
156 inline void DumpVar(const char *szName, char value)
\r
158 std::lock_guard<std::mutex> lck(mtx);
\r
159 DLOG << "[chr]: " << szName << "='" << value << "'" << std::endl;
\r
162 inline void DumpVar(const char *szName, bool value)
\r
164 std::lock_guard<std::mutex> lck(mtx);
\r
165 DLOG << "[bool]: " << szName << "=" << (value ? "true" : "false") << std::endl;
\r
168 inline void DumpVar(const char *szName, short value)
\r
170 std::lock_guard<std::mutex> lck(mtx);
\r
171 DLOG << "[shrt]: " << szName << "=" << value << std::endl;
\r
174 inline void DumpVar(const char *szName, int value)
\r
176 std::lock_guard<std::mutex> lck(mtx);
\r
177 DLOG << "[int]: " << szName << "=" << value << std::endl;
\r
180 inline void DumpVar(const char *szName, long value)
\r
182 std::lock_guard<std::mutex> lck(mtx);
\r
183 DLOG << "[long]: " << szName << "=" << value << std::endl;
\r
186 inline void DumpVar(const char *szName, double value)
\r
188 std::lock_guard<std::mutex> lck(mtx);
\r
189 DLOG << "[dbl]: " << szName << "=" << value << std::endl;
\r
192 inline void DumpVar(const char *szName, unsigned char value)
\r
194 std::lock_guard<std::mutex> lck(mtx);
\r
195 DLOG << "[byte]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
\r
198 inline void DumpVar(const char *szName, unsigned short value)
\r
200 std::lock_guard<std::mutex> lck(mtx);
\r
201 DLOG << "[word]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
\r
204 inline void DumpVar(const char *szName, unsigned int value)
\r
206 std::lock_guard<std::mutex> lck(mtx);
\r
207 DLOG << "[uint]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
\r
210 inline void DumpVar(const char *szName, unsigned long value)
\r
212 std::lock_guard<std::mutex> lck(mtx);
\r
213 DLOG << "[dword]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
\r
216 inline void DumpVar(const char *szName, const char* value)
\r
218 std::lock_guard<std::mutex> lck(mtx);
\r
219 DLOG << "[str]: " << szName << "=\"" << (value ? value : "") << "\"" << std::endl;
\r
222 inline void DumpVar(const char *szName, const std::string &value)
\r
224 std::lock_guard<std::mutex> lck(mtx);
\r
225 DLOG << "[Str]: " << szName << "=\"" << value << "\"" << std::endl;
\r
228 inline void DumpVar(const char *szName, const std::wstring &value)
\r
230 std::lock_guard<std::mutex> lck(mtx);
\r
231 DLOG << "[WStr]: " << szName << "=\"" << w2s(value) << "\"" << std::endl;
\r
234 #ifndef MB_IGNORE_QT
\r
235 inline void DumpVar(const char *szName, const QString &value)
\r
237 std::lock_guard<std::mutex> lck(mtx);
\r
238 DLOG << "[QStr]: " << szName << "=\"" << value.toStdString() << "\"" << std::endl;
\r
241 inline void DumpVar(const char *szName, const QStringList &value)
\r
243 std::lock_guard<std::mutex> lck(mtx);
\r
244 DLOG << "[QStrLst]: " << szName << "=[len=" << value.length() << "] {";
\r
246 QStringList::const_iterator it = value.constBegin();
\r
247 for ( ; it != value.constEnd(); ++it)
\r
249 DLOG << (first ? "" : ",") << "\"" << (*it).toStdString() << "\"";
\r
252 DLOG << "}" << std::endl;
\r
256 inline void DumpVar(const char *szName, const void* value)
\r
258 std::lock_guard<std::mutex> lck(mtx);
\r
259 DLOG << "[ptr]: " << szName << "=" << value << std::endl;
\r
263 // Collection of primitive types
\r
264 inline void DumpVar(const char *szName, const std::set<int> &values)
\r
266 std::lock_guard<std::mutex> lck(mtx);
\r
267 DLOG << "[intSet]: " << szName << "={" << values.size() << "}[";
\r
268 bool bFirst = true;
\r
269 for (auto it=values.cbegin(); it!=values.cend(); ++it) {
\r
270 DLOG << (bFirst ? "" : ",") << *it;
\r
273 DLOG << "]" << std::endl;
\r
276 inline void DumpVar(const char *szName, const std::vector<int> &values)
\r
278 std::lock_guard<std::mutex> lck(mtx);
\r
279 DLOG << "[intVect]: " << szName << "={" << values.size() << "}[";
\r
280 bool bFirst = true;
\r
281 for (auto it=values.cbegin(); it!=values.cend(); ++it) {
\r
282 DLOG << (bFirst ? "" : ",") << *it;
\r
285 DLOG << "]" << std::endl;
\r
288 inline void DumpVar(const char *szName, const std::list<bool>& values)
\r
290 std::lock_guard<std::mutex> lck(mtx);
\r
291 DLOG << "[boolList]: " << szName << "={" << values.size() << "}[";
\r
292 bool bFirst = true;
\r
293 for (auto it=values.cbegin(); it!=values.cend(); ++it) {
\r
294 DLOG << (bFirst ? "" : ",") << (*it ? "Y" : "N");
\r
297 DLOG << "]" << std::endl;
\r
300 inline void DumpVar(const char *szName, const std::list<std::string> &values)
\r
302 std::lock_guard<std::mutex> lck(mtx);
\r
303 DLOG << "[strLst]: " << szName << "={" << values.size() << "}[";
\r
304 bool bFirst = true;
\r
305 for (auto it=values.cbegin(); it!=values.cend(); ++it) {
\r
306 DLOG << (bFirst ? "\"" : ", \"") << *it << "\"";
\r
309 DLOG << "]" << std::endl;
\r
312 #endif // MBDebug_HeaderFile
\r