I have a debugger class which implements a printf() c style method. It looks like this:
#define NO_DEBUG 0
#define NO_PREFIX 1
#define DEBUG_INFO 2
#define DEBUG_SUCCESS 3
#define DEBUG_WARN 4
#define DEBUG_ERROR 5
#define MAX_DEBUG_LEVEL 5
#define DEBUG_INFO_PREFIX "[INFO] "
#define DEBUG_SUCCESS_PREFIX "[SUCCESS] "
#define DEBUG_WARN_PREFIX "[WARN] "
#define DEBUG_ERROR_PREFIX "[ERROR] "
/*
* Printing debug information to Serial in c printf style
* If the level is higher then the global debug level or
* the level is NO_DEBUG ( see debug.h ) then the message is not printed.
*/
void DebugSystem::print(byte level, const char *message, ...){
if( level > debugLevel || level == NO_DEBUG ){ return; }
char buffer[PRINT_BUFFER_SIZE];
printPrefix(level);
va_list args;
va_start (args, message);
vsprintf (buffer, message, args);
Serial.print(buffer);
va_end (args);
}
It is used like this:
int count = 0;
debug.print(DEBUG_INFO,"Test message: %s,%d\n","testMSG",count);
debug.print(DEBUG_SUCCESS,"Test message: %s,%d\n","testMSG",count);
debug.print(DEBUG_WARN,"Test message: %s,%d\n","testMSG",count);
debug.print(DEBUG_ERROR,"Test message: %s,%d\n","testMSG",count);
It is working very well. Now i want to add a prefix before the message which i have implemented like this:
/*
* Printing a prefix before the message based on it's level.
* Levels:
* - INFO prefix --> [INFO]
* - WARN prefix --> [WARN]
* - ERROR prefix --> [ERROR]
* - SUCCESS prefix --> [SUCCESS]
*/
void DebugSystem::printPrefix(byte level){
if( !levelPrefix || level == NO_PREFIX ){ return; }
const char* prefix = level == DEBUG_ERROR ? DEBUG_ERROR_PREFIX
: level == DEBUG_WARN ? DEBUG_WARN_PREFIX
: level == DEBUG_SUCCESS ? DEBUG_SUCCESS_PREFIX
: DEBUG_INFO_PREFIX;
Serial.print(prefix);
}
But i have a small problem. If the user want's to print \n at the beginning of the message, the output will be ill formatted.
Here is an example:
debug.print(DEBUG_INFO,"Test message: %s\n","TEST");
debug.print(DEBUG_INFO,"\nTest message: %s\n","TEST");
Output:
[INFO] Test message: TEST
[INFO]
Test message: TEST
For this to work properly i have two solutions in mind Either check the first param ( i don't know how ) and if it is a new line '\n' character i remove it and print it before the prefix or i have to inject my prefix after the first \n character into the message.
I'm using Arduino framework to do all of this but i can't think of an elegant solution.
Expected output of this test message would be:
[INFO] Test message: TEST
[INFO] Test message: TEST
Ofc the problem is not just with the \n but any format character in the string. I need a robust solution, some regex or something to detect if there is a formatter character in the beginning of the arguments, remove and print it before the prefix.