summaryrefslogtreecommitdiff
path: root/AK/LogStream.h
blob: ff685caa5cf6a482e6b05268d20a1f775f5ca097 (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
135
136
#pragma once

#include <AK/kstdio.h>

#ifdef USERLAND
#    include <AK/ScopedValueRollback.h>
#    include <AK/StringView.h>
#    include <errno.h>
#    include <unistd.h>
#endif

namespace AK {

class String;
class StringView;

class TStyle {
public:
    enum NoneTag { None };

    enum Color {
        Black = 0,
        Red,
        Green,
        Brown,
        Blue,
        Magenta,
        Cyan,
        LightGray,
        DarkGray,
        BrightRed,
        BrightGreen,
        Yellow,
        BrightBlue,
        BrightMagenta,
        BrightCyan,
        White,
        NoColor = 255,
    };
    enum Attribute {
        NoAttribute = 0,
        Bold = 1,
    };

    TStyle() {}
    TStyle(NoneTag) {}
    TStyle(Color color, unsigned attributes = NoAttribute)
        : m_color(color)
        , m_attributes(attributes)
    {
    }

    ~TStyle() {}

    Color color() const { return m_color; }
    unsigned attributes() const { return m_attributes; }

private:
    Color m_color { NoColor };
    unsigned m_attributes { NoAttribute };
};

class LogStream {
public:
    LogStream()
#ifdef USERLAND
        : m_errno_restorer(errno)
#endif
    {
    }
    virtual ~LogStream() {}

    virtual void write(const char*, int) const = 0;

protected:
    friend const LogStream& operator<<(const LogStream&, const TStyle&);
    mutable bool m_needs_style_reset { false };

private:
#ifdef USERLAND
    ScopedValueRollback<int> m_errno_restorer;
#endif
};

class DebugLogStream final : public LogStream {
public:
    DebugLogStream() {}
    virtual ~DebugLogStream() override
    {
        if (m_needs_style_reset)
            write("\033[0m", 4);
        char newline = '\n';
        write(&newline, 1);
    }

    virtual void write(const char* characters, int length) const override
    {
        dbgputstr(characters, length);
    }
};

inline const LogStream& operator<<(const LogStream& stream, const char* value)
{
    int length = 0;
    const char* p = value;
    while (*(p++))
        ++length;
    stream.write(value, length);
    return stream;
}

const LogStream& operator<<(const LogStream&, const String&);
const LogStream& operator<<(const LogStream&, const StringView&);
const LogStream& operator<<(const LogStream&, int);
const LogStream& operator<<(const LogStream&, unsigned);
const LogStream& operator<<(const LogStream&, const void*);
const LogStream& operator<<(const LogStream& stream, const TStyle&);

inline const LogStream& operator<<(const LogStream& stream, char value)
{
    stream.write(&value, 1);
    return stream;
}

inline const LogStream& operator<<(const LogStream& stream, bool value)
{
    return stream << (value ? "true" : "false");
}

DebugLogStream dbg();

}

using AK::dbg;
using AK::LogStream;
using AK::TStyle;