Logger C
label.h
#ifndef LABEL_H
#define LABEL_H
typedef enum {
labelString,
labelInt,
labelFloat,
labelDouble,
labelBool
} LoggerLabelType;
typedef struct {
LoggerLabelType type;
char *name;
union {
char *s;
int i;
float f;
double d;
bool b;
} value;
} LoggerLabel;
LoggerLabel* LabelError(const char *value);
LoggerLabel *LabelString(const char *name, const char *value);
LoggerLabel *LabelInt(const char *name, int value);
LoggerLabel *LabelFloat(const char *name, float value);
LoggerLabel *LabelDouble(const char *name, double value);
LoggerLabel *LabelBool(const char *name, bool value);
void LabelFree(LoggerLabel*);
void LabelPrint(LoggerLabel*);
#endif // LABEL_H
label.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "label.h"
static const char *boolName[2] = {
"false",
"true",
};
static LoggerLabel* labelInit(const char* name, LoggerLabelType type) {
LoggerLabel* label = calloc(1, sizeof(LoggerLabel));
unsigned long nameLength = strlen(name);
label->type = type;
label->name = calloc(nameLength + 1, sizeof(char));
strncpy(label->name, name, nameLength);
return label;
}
LoggerLabel* LabelError(const char *value) {
return LabelString("err", value);
}
LoggerLabel* LabelString(const char* name, const char* value) {
LoggerLabel* label = labelInit(name, labelString);
unsigned long valueLength = strlen(value);
label->value.s = calloc(valueLength + 1, sizeof(char));
strncpy(label->value.s, value, valueLength);
return label;
}
LoggerLabel* LabelInt(const char* name, int value) {
LoggerLabel* label = labelInit(name, labelInt);
label->value.i = value;
return label;
}
LoggerLabel* LabelFloat(const char* name, float value) {
LoggerLabel* label = labelInit(name, labelFloat);
label->value.f = value;
return label;
}
LoggerLabel* LabelDouble(const char* name, double value) {
LoggerLabel* label = labelInit(name, labelDouble);
label->value.d = value;
return label;
}
LoggerLabel* LabelBool(const char* name, bool value) {
LoggerLabel* label = labelInit(name, labelBool);
label->value.b = value;
return label;
}
void LabelFree(LoggerLabel* label) {
switch(label->type) {
case labelString:
free(label->value.s);
break;
default:
break;
}
free(label);
}
void LabelPrint(LoggerLabel* label) {
printf("%s=", label->name);
switch(label->type) {
case labelString:
printf("%s", label->value.s);
break;
case labelInt:
printf("%d", label->value.i);
break;
case labelFloat:
printf("%f", label->value.f);
break;
case labelDouble:
printf("%f", label->value.d);
break;
case labelBool:
printf("%s", boolName[label->value.b]);
default:
break;
}
}
logger.h
#ifndef LOGGER_H
#define LOGGER_H
#include <stdarg.h>
// __WILL_BE_OWNED by the receiving end. no need to free a pointer after that, cannot use it anymore
#define __WILL_BE_OWNED
typedef enum {
DEBUG,
INFO,
WARN,
ERROR,
LEVELS
} LogLevel;
void printLog(LogLevel level, const char *message, __WILL_BE_OWNED ...);
#define LOG(level, message, ...) \
printLog(level, message, ##__VA_ARGS__, NULL) // https://stackoverflow.com/a/18968248
#include "logger/label.h"
#endif // LOGGER_H
logger.c
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include "logger.h"
#include "label.h"
static const char *name[LEVELS] = {
"DEBUG",
"INFO",
"WARN",
"ERROR",
};
void printLog(LogLevel level, const char *message, ...) {
va_list argumentList;
printf("[%s]\t%s\t", name[level], message);
va_start(argumentList, message);
LoggerLabel *label = va_arg(argumentList, LoggerLabel*);
for ( ; label != NULL; ) {
LabelPrint(label);
LabelFree(label);
if ((label = va_arg(argumentList, LoggerLabel*)) != NULL) {
printf(",");
}
}
puts("");
}