#ifndef __Tracer__
#define __Tracer__
#include <iostream>
#include <iomanip>
#include "Lib/Output.hpp"
namespace Debug {
namespace Tracer {
void printStack();
};
struct DebugConfig {
unsigned indent = 0;
};
static DebugConfig debugConfig;
struct DebugIndentGuard {
DebugIndentGuard() { debugConfig.indent++; }
~DebugIndentGuard() { debugConfig.indent--; }
};
template<class... As>
struct _printDbg {
void operator()(const As&... msg);
};
template<> struct _printDbg<>{
void operator()() { }
};
template<class A, class... As> struct _printDbg<A, As...>{
void operator()(const A& a, const As&... as) {
std::cout << a;
_printDbg<As...>{}(as...);
}
};
template<class... A> void printDbg(const char* file, int line, const A&... msg)
{
unsigned width = 60;
std::cout << "[ debug ] ";
for (const char* c = file; *c != 0 && width > 0; c++, width--) {
std::cout << *c;
}
for (unsigned i = 0; i < width; i++) {
std::cout << ' ';
}
std::cout << "@" << std::setw(5) << line << ":";
std::cout << Lib::Output::repeat(" ", debugConfig.indent);
_printDbg<A...>{}(msg...);
std::cout << std::endl;
}
}
#if VDEBUG
#ifdef ABSOLUTE_SOURCE_DIR
#define __REL_FILE__ (&__FILE__[sizeof(ABSOLUTE_SOURCE_DIR) / sizeof(ABSOLUTE_SOURCE_DIR[0])])
#else
#define __REL_FILE__ __FILE__
#endif
# define DBG(...) { Debug::printDbg(__REL_FILE__, __LINE__, __VA_ARGS__); }
# define DBG_INDENT Debug::DebugIndentGuard {};
# define WARN(...) { DBG("WARNING: ", __VA_ARGS__); }
# define DBGE(x) DBG(#x, " = ", x)
#else
# define WARN(...) {}
# define DBG_INDENT {}
# define DBG(...) {}
# define DBGE(x) {}
#endif
#endif