--- /dev/null
+#ifndef MBDebug_HeaderFile
+#define MBDebug_HeaderFile
+
+//---------------------------------------------------------------
+// Usage of the logging facilities:
+//
+// (1) At the beginning of each class file to be debugged, there
+// should be a static string variable defined with the name
+// of the class. Then, include the "MBDebug.h" header file.
+//
+// //---------------------------------------------------------
+// #define USE_DEBUG
+// //#define MB_IGNORE_QT
+// //#define MB_FULL_DUMP
+// #define MBCLASSNAME "ClassName"
+// #include "MBDebug.h"
+// // <-- insert includes for addtional debug headers here!
+// //---------------------------------------------------------
+//
+// (2) At the beginning of each class method, call the DBG_FUN
+// macro.
+//
+// int ClassName::MyMethod(int x)
+// {
+// DBG_FUN();
+// ...
+// }
+//
+// NOTE: For static methods, call the DBG_FUNC() macro!!
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// This debugging/logging class is a "header-only" solution and
+// does NOT require any additional implementation (.cpp) file!
+//---------------------------------------------------------------
+
+#include <iostream>
+#include <string>
+#include <locale>
+#include <codecvt>
+#include <list>
+#include <map>
+#include <set>
+#include <vector>
+#include <mutex>
+#include <thread>
+#ifndef MB_IGNORE_QT
+# include <QString>
+# include <QStringList>
+#endif
+
+static std::mutex mtx;
+
+//---------------------------------------------------------------
+// Set the debug flags dependent on the preprocessor definitions
+//---------------------------------------------------------------
+#ifdef USE_DEBUG
+# define MBS_DEBUG_FLAG MBDebug::DF_DEBUG
+#else
+# define MBS_DEBUG_FLAG 0
+#endif /*DEBUG*/
+
+#define MBS_DBG_FLAGS (MBS_DEBUG_FLAG)
+
+
+//---------------------------------------------------------------
+// Define the global debug macros
+//---------------------------------------------------------------
+#define DLOG MBDebug::LogPrint()
+#define RETURN(var) { RET(var); return (var); }
+
+#ifdef USE_DEBUG
+
+# define DBG_FUN() MBDebug _dbg(MBCLASSNAME, __FUNCTION__, MBS_DBG_FLAGS, (void*)this)
+# define DBG_FUNC() MBDebug _dbg(MBCLASSNAME, __FUNCTION__, MBS_DBG_FLAGS)
+# define DBG_FUNB(blk) MBDebug _dbg(MBCLASSNAME, blk, MBS_DBG_FLAGS)
+# define MSGEL(txt) MBDebug::LogPrint() << ":" << txt << std::endl
+# define PRINT(txt) MBDebug::LogPrint() << txt
+# define SHOW2(var,typ) do { PRINT(std::this_thread::get_id()); DumpVar(#var,(typ)(var)); } while (0)
+# define SHOW(var) do { PRINT(std::this_thread::get_id()); DumpVar(#var,var); } while (0)
+# define ARG(var) do { PRINT(std::this_thread::get_id() << ":in:"); DumpVar(#var,var); } while (0)
+# define ARG2(var,typ) do { PRINT(std::this_thread::get_id() << ":in:"); DumpVar(#var,(typ)(var)); } while (0)
+# define RET(var) do { PRINT(std::this_thread::get_id() << ":out:"); DumpVar(#var,var); } while (0)
+# define MSG(txt) MBDebug::LogPrint() << std::this_thread::get_id() << ":" << txt
+
+#else /*!USE_DEBUG*/
+
+# define DBG_FUN()
+# define DBG_FUNC()
+# define DBG_FUNB(blk)
+# define MSGEL(txt)
+# define PRINT(txt)
+# define SHOW2(var,typ)
+# define SHOW(var)
+# define ARG(var)
+# define ARG2(var,typ)
+# define RET(var)
+# define MSG(txt)
+
+#endif /*USE_DEBUG*/
+
+
+//---------------------------------------------------------------
+// Declare the debugging and profiling class
+//---------------------------------------------------------------
+class MBDebug
+{
+public:
+ enum {
+ DF_NONE = 0x00, // no debug
+ DF_DEBUG = 0x01 // debug a function
+ };
+
+ MBDebug(const char* aClassName, const char* aFuncName, const short aFlag, void* aThis=NULL)
+ :mClassName(aClassName),mFuncName(aFuncName),mThis(aThis),mFlags((unsigned char)aFlag)
+ {
+ if (mFlags & (DF_DEBUG))
+ {
+ std::lock_guard<std::mutex> lck(mtx);
+ std::cout << std::this_thread::get_id() << ":{ENTER: " << mClassName + "::" + mFuncName;
+ if (mThis) std::cout << "(this=" << mThis << ")";
+ std::cout << std::endl;
+ }
+ }
+ virtual ~MBDebug()
+ {
+ if (mFlags & (DF_DEBUG))
+ {
+ std::lock_guard<std::mutex> lck(mtx);
+ std::cout << std::this_thread::get_id() << ":}LEAVE: " << mClassName << "::" << mFuncName << std::endl;
+ }
+ }
+
+ // Log file output management
+ static std::ostream& LogPrint() { return std::cout; }
+
+private:
+ std::string mClassName; // Name of class to be debugged
+ std::string mFuncName; // Name of function to be debugged
+ void* mThis; // The "this" pointer to the class being debugged
+ unsigned char mFlags; // Debug mode flags
+};
+
+
+
+#define YesNo(b) (b ? "Yes" : "No")
+
+
+
+inline std::string w2s(std::wstring ws)
+{
+ using convert_typeX = std::codecvt_utf8<wchar_t>;
+ std::wstring_convert<convert_typeX, wchar_t> converterX;
+ return(converterX.to_bytes(ws));
+}
+
+// Primitive types
+inline void DumpVar(const char *szName, char value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[chr]: " << szName << "='" << value << "'" << std::endl;
+}
+
+inline void DumpVar(const char *szName, bool value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[bool]: " << szName << "=" << (value ? "true" : "false") << std::endl;
+}
+
+inline void DumpVar(const char *szName, short value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[shrt]: " << szName << "=" << value << std::endl;
+}
+
+inline void DumpVar(const char *szName, int value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[int]: " << szName << "=" << value << std::endl;
+}
+
+inline void DumpVar(const char *szName, long value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[long]: " << szName << "=" << value << std::endl;
+}
+
+inline void DumpVar(const char *szName, double value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[dbl]: " << szName << "=" << value << std::endl;
+}
+
+inline void DumpVar(const char *szName, unsigned char value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[byte]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
+}
+
+inline void DumpVar(const char *szName, unsigned short value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[word]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
+}
+
+inline void DumpVar(const char *szName, unsigned int value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[uint]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
+}
+
+inline void DumpVar(const char *szName, unsigned long value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[dword]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
+}
+
+inline void DumpVar(const char *szName, const char* value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[str]: " << szName << "=\"" << (value ? value : "") << "\"" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::string &value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[Str]: " << szName << "=\"" << value << "\"" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::wstring &value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[WStr]: " << szName << "=\"" << w2s(value) << "\"" << std::endl;
+}
+
+#ifndef MB_IGNORE_QT
+inline void DumpVar(const char *szName, const QString &value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[QStr]: " << szName << "=\"" << value.toStdString() << "\"" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const QStringList &value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[QStrLst]: " << szName << "=[len=" << value.length() << "] {";
+ bool first = true;
+ QStringList::const_iterator it = value.constBegin();
+ for ( ; it != value.constEnd(); ++it)
+ {
+ DLOG << (first ? "" : ",") << "\"" << (*it).toStdString() << "\"";
+ first = false;
+ }
+ DLOG << "}" << std::endl;
+}
+#endif
+
+inline void DumpVar(const char *szName, const void* value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[ptr]: " << szName << "=" << value << std::endl;
+}
+
+
+// Collection of primitive types
+inline void DumpVar(const char *szName, const std::set<int> &values)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[intSet]: " << szName << "={" << values.size() << "}[";
+ bool bFirst = true;
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {
+ DLOG << (bFirst ? "" : ",") << *it;
+ bFirst = false;
+ }
+ DLOG << "]" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::vector<int> &values)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[intVect]: " << szName << "={" << values.size() << "}[";
+ bool bFirst = true;
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {
+ DLOG << (bFirst ? "" : ",") << *it;
+ bFirst = false;
+ }
+ DLOG << "]" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::list<bool>& values)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[boolList]: " << szName << "={" << values.size() << "}[";
+ bool bFirst = true;
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {
+ DLOG << (bFirst ? "" : ",") << (*it ? "Y" : "N");
+ bFirst = false;
+ }
+ DLOG << "]" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::list<std::string> &values)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[strLst]: " << szName << "={" << values.size() << "}[";
+ bool bFirst = true;
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {
+ DLOG << (bFirst ? "\"" : ", \"") << *it << "\"";
+ bFirst = false;
+ }
+ DLOG << "]" << std::endl;
+}
+
+#endif // MBDebug_HeaderFile
+
--- /dev/null
+#ifndef MBDebug_HeaderFile
+#define MBDebug_HeaderFile
+
+//---------------------------------------------------------------
+// Usage of the logging facilities:
+//
+// (1) At the beginning of each class file to be debugged, there
+// should be a static string variable defined with the name
+// of the class. Then, include the "MBDebug.h" header file.
+//
+// //---------------------------------------------------------
+// #define USE_DEBUG
+// //#define MB_IGNORE_QT
+// //#define MB_FULL_DUMP
+// #define MBCLASSNAME "ClassName"
+// #include "MBDebug.h"
+// // <-- insert includes for addtional debug headers here!
+// //---------------------------------------------------------
+//
+// (2) At the beginning of each class method, call the DBG_FUN
+// macro.
+//
+// int ClassName::MyMethod(int x)
+// {
+// DBG_FUN();
+// ...
+// }
+//
+// NOTE: For static methods, call the DBG_FUNC() macro!!
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// This debugging/logging class is a "header-only" solution and
+// does NOT require any additional implementation (.cpp) file!
+//---------------------------------------------------------------
+
+#include <iostream>
+#include <string>
+#include <locale>
+#include <codecvt>
+#include <list>
+#include <map>
+#include <set>
+#include <vector>
+#include <mutex>
+#include <thread>
+#ifndef MB_IGNORE_QT
+# include <QString>
+# include <QStringList>
+#endif
+
+static std::mutex mtx;
+
+//---------------------------------------------------------------
+// Set the debug flags dependent on the preprocessor definitions
+//---------------------------------------------------------------
+#ifdef USE_DEBUG
+# define MBS_DEBUG_FLAG MBDebug::DF_DEBUG
+#else
+# define MBS_DEBUG_FLAG 0
+#endif /*DEBUG*/
+
+#define MBS_DBG_FLAGS (MBS_DEBUG_FLAG)
+
+
+//---------------------------------------------------------------
+// Define the global debug macros
+//---------------------------------------------------------------
+#define DLOG MBDebug::LogPrint()
+#define RETURN(var) { RET(var); return (var); }
+
+#ifdef USE_DEBUG
+
+# define DBG_FUN() MBDebug _dbg(MBCLASSNAME, __FUNCTION__, MBS_DBG_FLAGS, (void*)this)
+# define DBG_FUNC() MBDebug _dbg(MBCLASSNAME, __FUNCTION__, MBS_DBG_FLAGS)
+# define DBG_FUNB(blk) MBDebug _dbg(MBCLASSNAME, blk, MBS_DBG_FLAGS)
+# define MSGEL(txt) MBDebug::LogPrint() << ":" << txt << std::endl
+# define PRINT(txt) MBDebug::LogPrint() << txt
+# define SHOW2(var,typ) do { PRINT(std::this_thread::get_id()); DumpVar(#var,(typ)(var)); } while (0)
+# define SHOW(var) do { PRINT(std::this_thread::get_id()); DumpVar(#var,var); } while (0)
+# define ARG(var) do { PRINT(std::this_thread::get_id() << ":in:"); DumpVar(#var,var); } while (0)
+# define ARG2(var,typ) do { PRINT(std::this_thread::get_id() << ":in:"); DumpVar(#var,(typ)(var)); } while (0)
+# define RET(var) do { PRINT(std::this_thread::get_id() << ":out:"); DumpVar(#var,var); } while (0)
+# define MSG(txt) MBDebug::LogPrint() << std::this_thread::get_id() << ":" << txt
+
+#else /*!USE_DEBUG*/
+
+# define DBG_FUN()
+# define DBG_FUNC()
+# define DBG_FUNB(blk)
+# define MSGEL(txt)
+# define PRINT(txt)
+# define SHOW2(var,typ)
+# define SHOW(var)
+# define ARG(var)
+# define ARG2(var,typ)
+# define RET(var)
+# define MSG(txt)
+
+#endif /*USE_DEBUG*/
+
+
+//---------------------------------------------------------------
+// Declare the debugging and profiling class
+//---------------------------------------------------------------
+class MBDebug
+{
+public:
+ enum {
+ DF_NONE = 0x00, // no debug
+ DF_DEBUG = 0x01 // debug a function
+ };
+
+ MBDebug(const char* aClassName, const char* aFuncName, const short aFlag, void* aThis=NULL)
+ :mClassName(aClassName),mFuncName(aFuncName),mThis(aThis),mFlags((unsigned char)aFlag)
+ {
+ if (mFlags & (DF_DEBUG))
+ {
+ std::lock_guard<std::mutex> lck(mtx);
+ std::cout << std::this_thread::get_id() << ":{ENTER: " << mClassName + "::" + mFuncName;
+ if (mThis) std::cout << "(this=" << mThis << ")";
+ std::cout << std::endl;
+ }
+ }
+ virtual ~MBDebug()
+ {
+ if (mFlags & (DF_DEBUG))
+ {
+ std::lock_guard<std::mutex> lck(mtx);
+ std::cout << std::this_thread::get_id() << ":}LEAVE: " << mClassName << "::" << mFuncName << std::endl;
+ }
+ }
+
+ // Log file output management
+ static std::ostream& LogPrint() { return std::cout; }
+
+private:
+ std::string mClassName; // Name of class to be debugged
+ std::string mFuncName; // Name of function to be debugged
+ void* mThis; // The "this" pointer to the class being debugged
+ unsigned char mFlags; // Debug mode flags
+};
+
+
+
+#define YesNo(b) (b ? "Yes" : "No")
+
+
+
+inline std::string w2s(std::wstring ws)
+{
+ using convert_typeX = std::codecvt_utf8<wchar_t>;
+ std::wstring_convert<convert_typeX, wchar_t> converterX;
+ return(converterX.to_bytes(ws));
+}
+
+// Primitive types
+inline void DumpVar(const char *szName, char value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[chr]: " << szName << "='" << value << "'" << std::endl;
+}
+
+inline void DumpVar(const char *szName, bool value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[bool]: " << szName << "=" << (value ? "true" : "false") << std::endl;
+}
+
+inline void DumpVar(const char *szName, short value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[shrt]: " << szName << "=" << value << std::endl;
+}
+
+inline void DumpVar(const char *szName, int value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[int]: " << szName << "=" << value << std::endl;
+}
+
+inline void DumpVar(const char *szName, long value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[long]: " << szName << "=" << value << std::endl;
+}
+
+inline void DumpVar(const char *szName, double value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[dbl]: " << szName << "=" << value << std::endl;
+}
+
+inline void DumpVar(const char *szName, unsigned char value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[byte]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
+}
+
+inline void DumpVar(const char *szName, unsigned short value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[word]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
+}
+
+inline void DumpVar(const char *szName, unsigned int value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[uint]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
+}
+
+inline void DumpVar(const char *szName, unsigned long value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[dword]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
+}
+
+inline void DumpVar(const char *szName, const char* value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[str]: " << szName << "=\"" << (value ? value : "") << "\"" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::string &value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[Str]: " << szName << "=\"" << value << "\"" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::wstring &value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[WStr]: " << szName << "=\"" << w2s(value) << "\"" << std::endl;
+}
+
+#ifndef MB_IGNORE_QT
+inline void DumpVar(const char *szName, const QString &value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[QStr]: " << szName << "=\"" << value.toStdString() << "\"" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const QStringList &value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[QStrLst]: " << szName << "=[len=" << value.length() << "] {";
+ bool first = true;
+ QStringList::const_iterator it = value.constBegin();
+ for ( ; it != value.constEnd(); ++it)
+ {
+ DLOG << (first ? "" : ",") << "\"" << (*it).toStdString() << "\"";
+ first = false;
+ }
+ DLOG << "}" << std::endl;
+}
+#endif
+
+inline void DumpVar(const char *szName, const void* value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[ptr]: " << szName << "=" << value << std::endl;
+}
+
+
+// Collection of primitive types
+inline void DumpVar(const char *szName, const std::set<int> &values)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[intSet]: " << szName << "={" << values.size() << "}[";
+ bool bFirst = true;
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {
+ DLOG << (bFirst ? "" : ",") << *it;
+ bFirst = false;
+ }
+ DLOG << "]" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::vector<int> &values)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[intVect]: " << szName << "={" << values.size() << "}[";
+ bool bFirst = true;
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {
+ DLOG << (bFirst ? "" : ",") << *it;
+ bFirst = false;
+ }
+ DLOG << "]" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::list<bool>& values)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[boolList]: " << szName << "={" << values.size() << "}[";
+ bool bFirst = true;
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {
+ DLOG << (bFirst ? "" : ",") << (*it ? "Y" : "N");
+ bFirst = false;
+ }
+ DLOG << "]" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::list<std::string> &values)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[strLst]: " << szName << "={" << values.size() << "}[";
+ bool bFirst = true;
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {
+ DLOG << (bFirst ? "\"" : ", \"") << *it << "\"";
+ bFirst = false;
+ }
+ DLOG << "]" << std::endl;
+}
+
+#endif // MBDebug_HeaderFile
+
--- /dev/null
+#ifndef MBDebug_HeaderFile
+#define MBDebug_HeaderFile
+
+//---------------------------------------------------------------
+// Usage of the logging facilities:
+//
+// (1) At the beginning of each class file to be debugged, there
+// should be a static string variable defined with the name
+// of the class. Then, include the "MBDebug.h" header file.
+//
+// //---------------------------------------------------------
+// #define USE_DEBUG
+// //#define MB_IGNORE_QT
+// //#define MB_FULL_DUMP
+// #define MBCLASSNAME "ClassName"
+// #include "MBDebug.h"
+// // <-- insert includes for addtional debug headers here!
+// //---------------------------------------------------------
+//
+// (2) At the beginning of each class method, call the DBG_FUN
+// macro.
+//
+// int ClassName::MyMethod(int x)
+// {
+// DBG_FUN();
+// ...
+// }
+//
+// NOTE: For static methods, call the DBG_FUNC() macro!!
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// This debugging/logging class is a "header-only" solution and
+// does NOT require any additional implementation (.cpp) file!
+//---------------------------------------------------------------
+
+#include <iostream>
+#include <string>
+#include <locale>
+#include <codecvt>
+#include <list>
+#include <map>
+#include <set>
+#include <vector>
+#include <mutex>
+#include <thread>
+#ifndef MB_IGNORE_QT
+# include <QString>
+# include <QStringList>
+#endif
+
+static std::mutex mtx;
+
+//---------------------------------------------------------------
+// Set the debug flags dependent on the preprocessor definitions
+//---------------------------------------------------------------
+#ifdef USE_DEBUG
+# define MBS_DEBUG_FLAG MBDebug::DF_DEBUG
+#else
+# define MBS_DEBUG_FLAG 0
+#endif /*DEBUG*/
+
+#define MBS_DBG_FLAGS (MBS_DEBUG_FLAG)
+
+
+//---------------------------------------------------------------
+// Define the global debug macros
+//---------------------------------------------------------------
+#define DLOG MBDebug::LogPrint()
+#define RETURN(var) { RET(var); return (var); }
+
+#ifdef USE_DEBUG
+
+# define DBG_FUN() MBDebug _dbg(MBCLASSNAME, __FUNCTION__, MBS_DBG_FLAGS, (void*)this)
+# define DBG_FUNC() MBDebug _dbg(MBCLASSNAME, __FUNCTION__, MBS_DBG_FLAGS)
+# define DBG_FUNB(blk) MBDebug _dbg(MBCLASSNAME, blk, MBS_DBG_FLAGS)
+# define MSGEL(txt) MBDebug::LogPrint() << ":" << txt << std::endl
+# define PRINT(txt) MBDebug::LogPrint() << txt
+# define SHOW2(var,typ) do { PRINT(std::this_thread::get_id()); DumpVar(#var,(typ)(var)); } while (0)
+# define SHOW(var) do { PRINT(std::this_thread::get_id()); DumpVar(#var,var); } while (0)
+# define ARG(var) do { PRINT(std::this_thread::get_id() << ":in:"); DumpVar(#var,var); } while (0)
+# define ARG2(var,typ) do { PRINT(std::this_thread::get_id() << ":in:"); DumpVar(#var,(typ)(var)); } while (0)
+# define RET(var) do { PRINT(std::this_thread::get_id() << ":out:"); DumpVar(#var,var); } while (0)
+# define MSG(txt) MBDebug::LogPrint() << std::this_thread::get_id() << ":" << txt
+
+#else /*!USE_DEBUG*/
+
+# define DBG_FUN()
+# define DBG_FUNC()
+# define DBG_FUNB(blk)
+# define MSGEL(txt)
+# define PRINT(txt)
+# define SHOW2(var,typ)
+# define SHOW(var)
+# define ARG(var)
+# define ARG2(var,typ)
+# define RET(var)
+# define MSG(txt)
+
+#endif /*USE_DEBUG*/
+
+
+//---------------------------------------------------------------
+// Declare the debugging and profiling class
+//---------------------------------------------------------------
+class MBDebug
+{
+public:
+ enum {
+ DF_NONE = 0x00, // no debug
+ DF_DEBUG = 0x01 // debug a function
+ };
+
+ MBDebug(const char* aClassName, const char* aFuncName, const short aFlag, void* aThis=NULL)
+ :mClassName(aClassName),mFuncName(aFuncName),mThis(aThis),mFlags((unsigned char)aFlag)
+ {
+ if (mFlags & (DF_DEBUG))
+ {
+ std::lock_guard<std::mutex> lck(mtx);
+ std::cout << std::this_thread::get_id() << ":{ENTER: " << mClassName + "::" + mFuncName;
+ if (mThis) std::cout << "(this=" << mThis << ")";
+ std::cout << std::endl;
+ }
+ }
+ virtual ~MBDebug()
+ {
+ if (mFlags & (DF_DEBUG))
+ {
+ std::lock_guard<std::mutex> lck(mtx);
+ std::cout << std::this_thread::get_id() << ":}LEAVE: " << mClassName << "::" << mFuncName << std::endl;
+ }
+ }
+
+ // Log file output management
+ static std::ostream& LogPrint() { return std::cout; }
+
+private:
+ std::string mClassName; // Name of class to be debugged
+ std::string mFuncName; // Name of function to be debugged
+ void* mThis; // The "this" pointer to the class being debugged
+ unsigned char mFlags; // Debug mode flags
+};
+
+
+
+#define YesNo(b) (b ? "Yes" : "No")
+
+
+
+inline std::string w2s(std::wstring ws)
+{
+ using convert_typeX = std::codecvt_utf8<wchar_t>;
+ std::wstring_convert<convert_typeX, wchar_t> converterX;
+ return(converterX.to_bytes(ws));
+}
+
+// Primitive types
+inline void DumpVar(const char *szName, char value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[chr]: " << szName << "='" << value << "'" << std::endl;
+}
+
+inline void DumpVar(const char *szName, bool value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[bool]: " << szName << "=" << (value ? "true" : "false") << std::endl;
+}
+
+inline void DumpVar(const char *szName, short value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[shrt]: " << szName << "=" << value << std::endl;
+}
+
+inline void DumpVar(const char *szName, int value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[int]: " << szName << "=" << value << std::endl;
+}
+
+inline void DumpVar(const char *szName, long value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[long]: " << szName << "=" << value << std::endl;
+}
+
+inline void DumpVar(const char *szName, double value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[dbl]: " << szName << "=" << value << std::endl;
+}
+
+inline void DumpVar(const char *szName, unsigned char value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[byte]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
+}
+
+inline void DumpVar(const char *szName, unsigned short value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[word]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
+}
+
+inline void DumpVar(const char *szName, unsigned int value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[uint]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
+}
+
+inline void DumpVar(const char *szName, unsigned long value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[dword]: " << szName << "=0x" << std::hex << value << std::dec << std::endl;
+}
+
+inline void DumpVar(const char *szName, const char* value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[str]: " << szName << "=\"" << (value ? value : "") << "\"" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::string &value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[Str]: " << szName << "=\"" << value << "\"" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::wstring &value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[WStr]: " << szName << "=\"" << w2s(value) << "\"" << std::endl;
+}
+
+#ifndef MB_IGNORE_QT
+inline void DumpVar(const char *szName, const QString &value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[QStr]: " << szName << "=\"" << value.toStdString() << "\"" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const QStringList &value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[QStrLst]: " << szName << "=[len=" << value.length() << "] {";
+ bool first = true;
+ QStringList::const_iterator it = value.constBegin();
+ for ( ; it != value.constEnd(); ++it)
+ {
+ DLOG << (first ? "" : ",") << "\"" << (*it).toStdString() << "\"";
+ first = false;
+ }
+ DLOG << "}" << std::endl;
+}
+#endif
+
+inline void DumpVar(const char *szName, const void* value)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[ptr]: " << szName << "=" << value << std::endl;
+}
+
+
+// Collection of primitive types
+inline void DumpVar(const char *szName, const std::set<int> &values)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[intSet]: " << szName << "={" << values.size() << "}[";
+ bool bFirst = true;
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {
+ DLOG << (bFirst ? "" : ",") << *it;
+ bFirst = false;
+ }
+ DLOG << "]" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::vector<int> &values)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[intVect]: " << szName << "={" << values.size() << "}[";
+ bool bFirst = true;
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {
+ DLOG << (bFirst ? "" : ",") << *it;
+ bFirst = false;
+ }
+ DLOG << "]" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::list<bool>& values)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[boolList]: " << szName << "={" << values.size() << "}[";
+ bool bFirst = true;
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {
+ DLOG << (bFirst ? "" : ",") << (*it ? "Y" : "N");
+ bFirst = false;
+ }
+ DLOG << "]" << std::endl;
+}
+
+inline void DumpVar(const char *szName, const std::list<std::string> &values)
+{
+ std::lock_guard<std::mutex> lck(mtx);
+ DLOG << "[strLst]: " << szName << "={" << values.size() << "}[";
+ bool bFirst = true;
+ for (auto it=values.cbegin(); it!=values.cend(); ++it) {
+ DLOG << (bFirst ? "\"" : ", \"") << *it << "\"";
+ bFirst = false;
+ }
+ DLOG << "]" << std::endl;
+}
+
+#endif // MBDebug_HeaderFile
+