2022-04-03 10:16:20 +02:00
|
|
|
/**
|
|
|
|
* @brief Writes messages to `debug.log` if `NDEBUG` is not defined.
|
|
|
|
* @author Christian Burger (christian@krikkel.de)
|
2022-04-08 21:00:10 +02:00
|
|
|
* @todo refactor macros
|
2022-04-03 10:16:20 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __DEBUG_H__
|
|
|
|
#define __DEBUG_H__
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
#include <string>
|
|
|
|
#include <ctime>
|
2022-04-08 21:00:10 +02:00
|
|
|
#include <locale>
|
2022-04-03 10:16:20 +02:00
|
|
|
|
|
|
|
namespace krikkel
|
|
|
|
{
|
|
|
|
class Debug
|
|
|
|
{
|
|
|
|
private:
|
2022-04-08 21:00:10 +02:00
|
|
|
std::fstream logFile;
|
2022-04-03 10:16:20 +02:00
|
|
|
static const int MAX_NUMBER_OF_SYSCALLS = 1024;
|
|
|
|
static const char * syscalls[MAX_NUMBER_OF_SYSCALLS];
|
|
|
|
|
|
|
|
Debug();
|
2022-04-08 21:00:10 +02:00
|
|
|
std::string getTimestamp();
|
|
|
|
std::string getUname();
|
2022-04-03 10:16:20 +02:00
|
|
|
|
|
|
|
public:
|
2022-04-08 21:00:10 +02:00
|
|
|
void log(std::string message, std::string fileName, int lineNo
|
|
|
|
, std::string functionName);
|
2022-04-03 10:16:20 +02:00
|
|
|
static Debug *getInstance();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#define __debug_log(message) krikkel::Debug::getInstance()\
|
|
|
|
->log(message, __FILE__, __LINE__, __func__)
|
|
|
|
|
2022-04-08 21:00:10 +02:00
|
|
|
|
|
|
|
/// @todo need an explanation on why and how to use this
|
|
|
|
/// this is the complete opposite of self-explanatory
|
|
|
|
#define __debug_stringify_switch_begin(closureName, __prop, __value) \
|
|
|
|
auto __debug_stringify__##closureName = [__prop, __value]() -> std::string \
|
|
|
|
{ \
|
|
|
|
std::string propertyName, valueString; \
|
|
|
|
switch(__prop) \
|
|
|
|
{
|
|
|
|
#define __debug_stringify_switch_case(caseTestValue) \
|
|
|
|
case caseTestValue: \
|
|
|
|
propertyName = (propertyName.empty() ? #caseTestValue : propertyName)
|
|
|
|
#define __debug_stringify_switch_case_end_bool(value) \
|
|
|
|
valueString = (value ? "true" : "false"); \
|
|
|
|
break
|
|
|
|
#define __debug_stringify_switch_case_end_string(value) \
|
|
|
|
valueString = "\"" + std::string(value) + "\""; \
|
|
|
|
break
|
|
|
|
#define __debug_stringify_switch_case_end_number(value) \
|
|
|
|
valueString = std::to_string(value); \
|
|
|
|
break;
|
|
|
|
#define __debug_stringify_switch_end(__prop) \
|
|
|
|
default: \
|
|
|
|
propertyName = "default case triggerd for " + std::to_string(__prop); \
|
|
|
|
break; \
|
|
|
|
} \
|
|
|
|
return propertyName + " = " + valueString; \
|
|
|
|
}
|
|
|
|
#define __debug_stringify_get_string(closureName) __debug_stringify__##closureName()
|
|
|
|
|
2022-04-08 22:03:12 +02:00
|
|
|
#define __debug_make_bytes_printable_table(__bytes) ([](std::string bytes) -> std::string \
|
2022-04-08 21:00:10 +02:00
|
|
|
{ \
|
|
|
|
std::locale loc; \
|
2022-04-08 22:03:12 +02:00
|
|
|
std::string result = "\n"; \
|
|
|
|
int index; \
|
|
|
|
for(index = 0; index < bytes.length(); ++index) \
|
2022-04-08 21:00:10 +02:00
|
|
|
{ \
|
2022-04-08 22:03:12 +02:00
|
|
|
static const uint8_t TRANSLATION_BUFFER_SIZE = 4; \
|
|
|
|
char translationBuffer[TRANSLATION_BUFFER_SIZE]; \
|
2022-04-08 21:00:10 +02:00
|
|
|
if(std::isprint(bytes[index], loc)) \
|
2022-04-08 22:03:12 +02:00
|
|
|
{ \
|
|
|
|
translationBuffer[0] = translationBuffer[1] = ' '; \
|
|
|
|
translationBuffer[2] = bytes[index]; \
|
|
|
|
translationBuffer[3] = '\0'; \
|
|
|
|
} \
|
2022-04-08 21:00:10 +02:00
|
|
|
else \
|
2022-04-08 22:03:12 +02:00
|
|
|
std::snprintf(translationBuffer, TRANSLATION_BUFFER_SIZE, " %02x", bytes[index]); \
|
|
|
|
result += (index % 16 == 0 ? " | " : " "); \
|
|
|
|
result += translationBuffer; \
|
2022-04-08 21:00:10 +02:00
|
|
|
if(index % 16 == 15) \
|
2022-04-08 22:03:12 +02:00
|
|
|
result += '\n'; \
|
2022-04-08 21:00:10 +02:00
|
|
|
} \
|
|
|
|
if(index % 16) \
|
2022-04-08 22:03:12 +02:00
|
|
|
result += '\n'; \
|
|
|
|
return result; \
|
2022-04-08 21:00:10 +02:00
|
|
|
} \
|
2022-04-08 22:03:12 +02:00
|
|
|
)(__bytes)
|
2022-04-08 21:00:10 +02:00
|
|
|
|
2022-04-08 22:03:12 +02:00
|
|
|
#define __debug_make_bytes_printable(__bytes) ([](std::string bytes) -> std::string \
|
2022-04-08 21:00:10 +02:00
|
|
|
{ \
|
|
|
|
std::locale loc; \
|
|
|
|
std::string result; \
|
2022-04-08 22:03:12 +02:00
|
|
|
for(char character : bytes) \
|
2022-04-08 21:00:10 +02:00
|
|
|
{ \
|
|
|
|
if(std::isprint(character, loc) && character != '<') \
|
|
|
|
result += character; \
|
|
|
|
else \
|
2022-04-08 22:03:12 +02:00
|
|
|
result += '<' + std::to_string(character) + '>'; \
|
2022-04-08 21:00:10 +02:00
|
|
|
} \
|
|
|
|
return result; \
|
2022-04-08 22:03:12 +02:00
|
|
|
})(__bytes)
|
2022-04-08 21:00:10 +02:00
|
|
|
|
2022-04-03 10:16:20 +02:00
|
|
|
#else
|
|
|
|
|
|
|
|
/// @todo check what's the business with this "((void)0)" instead of empty macro
|
|
|
|
#define __debug_log(message)
|
2022-04-08 21:00:10 +02:00
|
|
|
#define __debug_stringify_switch_begin(closureName, __prop, __value)
|
|
|
|
#define __debug_stringify_switch_case(caseTestValue)
|
|
|
|
#define __debug_stringify_switch_case_end_bool(value)
|
|
|
|
#define __debug_stringify_switch_case_end_string(value)
|
|
|
|
#define __debug_stringify_switch_case_end_number(value)
|
|
|
|
#define __debug_stringify_switch_end()
|
2022-04-08 22:03:12 +02:00
|
|
|
#define __debug_make_bytes_printable_table(bytes)
|
|
|
|
#define __debug_make_bytes_printable(bytes)
|
2022-04-03 10:16:20 +02:00
|
|
|
|
|
|
|
#endif /* NDEBUG */
|
|
|
|
|
|
|
|
#endif // __DEBUG_H__
|