Implement interface for log output, ensure it's safe too!
Closed this issue · 1 comments
hogsy commented
See platform_log.c
for initial implementation.
- Need a solution for supporting multi-level log messages, e.g. error, warning, debug and more (which can then be toggled on the fly?)
- This could probably be merged into the console?
Below is a quick mock I whipped up, completely untested but similar to what I'd like to do.
// EXAMPLE CODE, COMPLETELY UNTESTED AND PROBABLY FULL OF HOLES
// public
enum {
PL_LOG_LEVEL_HIGH = -1,
PL_LOG_LEVEL_MEDIUM = -2,
PL_LOG_LEVEL_LOW = -3,
PL_LOG_LEVEL_GRAPHICS = -4,
PL_LOG_LEVEL_FILESYSTEM = -5,
PL_LOG_LEVEL_END = 10,
};
///////////////////////////////////////////////////////////
// private
#define MAX_LOG_LEVELS 128
typedef struct LogLevel {
int id;
bool is_enabled;
char prefix[64]; // e.g. 'warning', 'error'
PLColour colour; // colour that it'll display
} LogLevel;
LogLevel levels[MAX_LOG_LEVELS];
LogLevel *GetLogLevel(int level) {
static bool mem_cleared = false;
if(!mem_cleared) {
memset(levels, 0, sizeof(LogLevel) * MAX_LOG_LEVELS);
mem_cleared = true;
plSetupLogLevel(PL_LOG_LEVEL_LOW, "pl", (PLColour){255, 255, 255}, false);
plSetupLogLevel(PL_LOG_LEVEL_MEDIUM, "pl-warn", (PLColour){255, 255, 0}, false);
plSetupLogLevel(PL_LOG_LEVEL_HIGH, "pl-error", (PLColour){255, 0, 0}, true);
plSetupLogLevel(PL_LOG_LEVEL_GRAPHICS, "pl-gfx", (PLColour){0, 255, 255}, false);
plSetupLogLevel(PL_LOG_LEVEL_FILESYSTEM, "pl-fs", (PLColour){0, 255, 255}, false);
}
// the following ensures there's no conflict
// between internal/external log levels
if(level < 0) {
level *= -1;
} else {
level += PL_LOG_LEVEL_END;
}
if(level > MAX_LOG_LEVELS) {
ReportError(PL_RESULT_ENDOFARRAY, "failed to find slot for log level %d", level);
return NULL;
}
LogLevel *l = &levels[level];
if(l->id == 0) {
// register it as a new level
l->id = level;
l->is_enabled = false;
}
return l;
}
///////////////////////////////////////////////////////////
// public
void plSetLogLevelStatus(int level, bool status) {
LogLevel *l = GetLogLevel(level);
if(l == NULL) {
return;
}
l->is_enabled = status;
}
void plSetupLogLevel(int level, const char *prefix, PLColour colour, bool status) {
LogLevel *l = GetLogLevel(level);
if(l == NULL) {
return;
}
if(prefix != NULL && prefix[0] != '\0') {
snprintf(l->prefix, sizeof(l->prefix), "%s", prefix);
}
l->colour = colour;
l->is_enabled = status;
}
void plLogMessage(int level, const char *msg, ...) {
LogLevel *l = GetLogLevel(level);
if(l == NULL) {
return;
}
if(!l->is_enabled) {
return;
}
char buf[4096] = {'\0'};
// add the prefix to the start
int c = 0;
if(l->prefix[0] != '\0') {
c = snprintf(buf, sizeof(buf), "[%s] %s:", plGetFormattedTime(), l->prefix);
} else {
c = snprintf(buf, sizeof(buf), "[%s]:", plGetFormattedTime());
}
va_list args;
va_start(args, msg);
vsnprintf(buf + c, sizeof(buf) - c, msg, args);
va_end(args);
// todo, decide how we're going to pass it to the console/log
}
hogsy commented
done