aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/utils/log.h
blob: b04740259d726fc94b28c4de58a1bd71c87edbb8 (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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
* Single.h/loghelper.h
* Copyright (C) 2017~2018 chai
*/
#ifndef __LOG_HELPER_H
#define __LOG_HELPER_H
#include <string> 
#include <iostream>
#include <fstream>
#include <stdarg.h>

class Loghelper
{
public:
    // logĿ
    enum Direction
    {
        DIR_CERR = 1 << 1, // ׼
        DIR_FILE = 1 << 2, // logļ
    };

    // ȼ
    enum Level
    {
        LV_NONE = 0,  // none   
        LV_ERROR = 1 << 1,  // error 
        LV_WARN = 1 << 2,  // warn 
        LV_INFO = 1 << 3,  // info 
        LV_DEBUG = 1 << 4, // debug 
        LV_ALL = 0xffffffff
    };

    static void log(Level _level, const char* _fmt, ...);

    // ض
    static void redirect(unsigned int _dir, char* _path = nullptr);

    // ɸѡȼ
    static void restrict(unsigned int levels);

    static void close();

private:
    static unsigned int dir;    // Ŀ
    static unsigned int levels; // ȼ
    static std::ofstream fs;    // ļ 
};

typedef Loghelper::Level Loglevel;

#ifdef LOGHELPER_IMPLEMENT

#define hasbit(flag, bit) ((flag & bit) == bit)

unsigned int Loghelper::dir = Loghelper::Direction::DIR_CERR;
unsigned int Loghelper::levels = Loghelper::Level::LV_ALL;
std::ofstream Loghelper::fs;

void Loghelper::log(Level _level, const char* _fmt, ...)
{
    if (!hasbit(levels, _level))
        return;
#define FORMAT_MSG_BUFFER_SIZE (204800)  
    char* levelStr = nullptr;
    switch (_level)
    {
    case LV_ERROR:
        levelStr = "Error: ";
        break;
    case LV_WARN:
        levelStr = "Warn: ";
        break;
    case LV_INFO:
        levelStr = "Info: ";
        break;
    case LV_DEBUG:
        levelStr = "Debug: ";
        break;
    default:
        levelStr = "Unknown: ";
        break;
    }
    char buffer[FORMAT_MSG_BUFFER_SIZE + 1] = { 0 };
    strcpy(buffer, levelStr);
    va_list args;
    va_start(args, _fmt);
    vsnprintf(buffer + strlen(buffer), FORMAT_MSG_BUFFER_SIZE, _fmt, args);
    va_end(args);
    if (hasbit(dir, DIR_CERR))
    {
        std::cerr << buffer << std::endl;
    }
    if (hasbit(dir, DIR_FILE))
    {
        fs << buffer << std::endl;
    }
#undef FORMAT_MSG_BUFFER_SIZE
}

// ض
void Loghelper::redirect(unsigned int _dir, char* _path)
{
    dir = _dir;
    if (hasbit(dir, DIR_FILE))
    {
        try
        {
            fs.open(_path, std::ios_base::app);
        }
        catch (std::ios_base::failure& e) {
            dir = DIR_CERR;
            log(Level::LV_WARN, "ضlog· %s ʧ", _path);
        }
    }
}

// ɸѡȼ
void Loghelper::restrict(unsigned int _levels)
{
    levels = _levels;
}

void Loghelper::close()
{
    if (!fs.fail())
        fs.close();
    fs.clear();
}

#undef hasbit

#endif

#endif