summaryrefslogtreecommitdiff
path: root/src/log.c
blob: 9d5781f36a93cecc4e44405696093b6d98dbe2a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include "../include/al/log.h"

//#define AL_LOG_SKIP
#define AL_LOG_TEMPLATE "%s:%d %s(): %s -> "
#define AL_LOG_TEMPLATE_SECTION AL_LOG_TEMPLATE"(%s) "

#define AL_LOG_MESSAGE_MAX ((size_t)(AL_LOG_MESSAGE_SIZE - 1u)) // Space for newline.

#ifndef AL_FORCE_DISABLE_OUTPUT
static s32 (*_al_print)(void *, u8, char *) = NULL;
static void *_al_log_userdata = NULL;

void al_set_print(s32 (*print_func)(void *, u8, char *), void *userdata)
{
    _al_print = print_func;
    _al_log_userdata = userdata;
}

static const char *levels[] = {
    [AL_LOG_INFO] = "info",
    [AL_LOG_WARN] = "warn",
    [AL_LOG_ERROR] = "error",
    [AL_LOG_DEBUG] = "debug",
    [AL_LOG_TRACE] = "trace"
};

#ifndef AL_LOG_SKIP
static __thread char messagebuf[AL_LOG_MESSAGE_SIZE];

static char *get_message_buffer(u8 level, const char *section, const char *name, const s32 line, const char *func, const char *fmt, va_list args)
{
    s32 prefix = 0;
    if (!section) {
        prefix = al_snprintf(messagebuf, AL_LOG_MESSAGE_MAX, AL_LOG_TEMPLATE, name, line, func, levels[level]);
    } else {
        prefix = al_snprintf(messagebuf, AL_LOG_MESSAGE_MAX, AL_LOG_TEMPLATE_SECTION, name, line, func, levels[level], section);
    }
    al_assert(prefix > 0);
    al_vsnprintf(messagebuf + prefix, AL_LOG_MESSAGE_MAX - (size_t)prefix, fmt, args);
    messagebuf[strcspn(messagebuf, "\r\n")] = '\0';
    return messagebuf;
}
#endif

s32 _al_logv(u8 level, const char *section, const char *name, const s32 line, const char *func, const char *fmt, va_list args)
{
#ifdef AL_LOG_SKIP
    s32 ret = 0;
    if (!section) {
        ret += al_printf(AL_LOG_TEMPLATE, name, line, func, levels[level]);
    } else {
        ret += al_printf(AL_LOG_TEMPLATE_SECTION, name, line, func, levels[level], section);
    }
    ret += al_vprintf(fmt, args);
    if (strcspn(fmt, "\r\n") == al_strlen(fmt)) {
        ret += al_printf("\n");
    }
    return ret;
#else
    al_assert(_al_print && "Global print method not set.");
    return _al_print(_al_log_userdata, level, get_message_buffer(level, section, name, line, func, fmt, args));
#endif
}

s32 _al_log(u8 level, const char *section, const char *name, const s32 line, const char *func, const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    s32 ret = _al_logv(level, section, name, line, func, fmt, args);
    va_end(args);
    return ret;
}
#else
void al_set_print(s32 (*print_func)(void *, u8, char *), void *userdata) { (void)print_func; (void)userdata; }
s32 _al_logv(u8 level, const char *section, const char *name, const s32 line, const char *func, const char *fmt, va_list args) { (void)level; (void)section; (void)name; (void)line; (void)func; (void)fmt; (void)args; return 0; }
s32 _al_log(u8 level, const char *section, const char *name, const s32 line, const char *func, const char *fmt, ...) { (void)level; (void)section; (void)name; (void)line; (void)func; (void)fmt; return 0; }
#endif