File: debugging.hpp

package info (click to toggle)
openmw 0.47.0-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 23,276 kB
  • sloc: cpp: 249,935; xml: 1,978; sh: 1,327; python: 63; makefile: 26
file content (143 lines) | stat: -rw-r--r-- 3,456 bytes parent folder | download
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
137
138
139
140
141
142
143
#ifndef DEBUG_DEBUGGING_H
#define DEBUG_DEBUGGING_H

#include <boost/filesystem/fstream.hpp>
#include <boost/iostreams/stream.hpp>

#include <components/files/configurationmanager.hpp>

#include <SDL_messagebox.h>

#include "debuglog.hpp"

#if defined _WIN32 && defined _DEBUG
#   undef WIN32_LEAN_AND_MEAN
#   define WIN32_LEAN_AND_MEAN
#   include <windows.h>
#endif

namespace Debug
{
    // ANSI colors for terminal
    enum Color
    {
        Reset = 0,
        DarkGray = 90,
        Red = 91,
        Yellow = 93
    };

    class DebugOutputBase : public boost::iostreams::sink
    {
    public:
        DebugOutputBase()
        {
            if (CurrentDebugLevel == NoLevel)
                fillCurrentDebugLevel();
        }

        virtual std::streamsize write(const char *str, std::streamsize size);

        virtual ~DebugOutputBase() = default;

    protected:
        static Level getLevelMarker(const char *str);

        static void fillCurrentDebugLevel();

        virtual std::streamsize writeImpl(const char *str, std::streamsize size, Level debugLevel)
        {
            return size;
        }
    };

#ifdef _WIN32
    bool attachParentConsole();
#endif

#if defined _WIN32 && defined _DEBUG
    class DebugOutput : public DebugOutputBase
    {
    public:
        std::streamsize writeImpl(const char *str, std::streamsize size, Level debugLevel)
        {
            // Make a copy for null termination
            std::string tmp (str, static_cast<unsigned int>(size));
            // Write string to Visual Studio Debug output
            OutputDebugString (tmp.c_str ());
            return size;
        }

        virtual ~DebugOutput() {}
    };
#else

    class Tee : public DebugOutputBase
    {
    public:
        Tee(std::ostream &stream, std::ostream &stream2)
            : out(stream), out2(stream2)
        {
            // TODO: check which stream is stderr?
            mUseColor = useColoredOutput();

            mColors[Error] = Red;
            mColors[Warning] = Yellow;
            mColors[Info] = Reset;
            mColors[Verbose] = DarkGray;
            mColors[Debug] = DarkGray;
            mColors[NoLevel] = Reset;
        }

        std::streamsize writeImpl(const char *str, std::streamsize size, Level debugLevel) override
        {
            out.write (str, size);
            out.flush();

            if(mUseColor)
            {
                out2 << "\033[0;" << mColors[debugLevel] << "m";
                out2.write (str, size);
                out2 << "\033[0;" << Reset << "m";
            }
            else
            {
                out2.write(str, size);
            }
            out2.flush();

            return size;
        }

        virtual ~Tee() {}

    private:

        static bool useColoredOutput()
        {
    // Note: cmd.exe in Win10 should support ANSI colors, but in its own way.
#if defined(_WIN32)
            return 0;
#else
            char *term = getenv("TERM");
            bool useColor = term && !getenv("NO_COLOR") && isatty(fileno(stderr));

            return useColor;
#endif
        }

        std::ostream &out;
        std::ostream &out2;
        bool mUseColor;

        std::map<Level, int> mColors;
    };
#endif
}

// Can be used to print messages without timestamps
std::ostream& getRawStdout();

int wrapApplication(int (*innerApplication)(int argc, char *argv[]), int argc, char *argv[], const std::string& appName);

#endif