-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy patheasylog.h
169 lines (147 loc) · 3.96 KB
/
easylog.h
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/* easylog.h - a fairly minimal logging-to-file implementation
Adrian Groves, FMRIB Image Analysis Group
Copyright (C) 2007-2008 University of Oxford */
/* CCOPYRIGHT */
#pragma once
#include <assert.h>
#include <iostream>
#include <map>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
/**
* Use LOG just like you'd use cout. (i.e. LOG << your_data << endl;)
* Your class must be derived from Loggable.
*
* If the log member variable m_log is not set, log output goes to stderr
*/
#define LOG ((m_log == 0) ? std::cerr : m_log->LogStream())
#define LOG_ERR(x) ((void)((LOG << x)))
#define WARN_ONCE(x) \
if (m_log) \
m_log->WarnOnce(x)
#define WARN_ALWAYS(x) \
if (m_log) \
m_log->WarnAlways(x)
/**
* Sends logging information to an output stream
*
* StartLog() is used to tell the logger where to put the output - any log
* calls made before this are stored in a temporary stringstream and then
* flushed to the log once StartLog is called.
*
* If you want to dump variables directly to this stream, just implement
* std::ostream& operator<<(std::ostream& stream, const your_type& data);
*/
class EasyLog
{
public:
/**
* Log output to an existing stream
*
* This might be std::cout/cerr or something else, e.g. a
* stringstream.
*/
EasyLog();
~EasyLog();
/**
* Log output to a file
*
* The file will be called 'logfile'
*
* @param outDir Name of a directory in which to put the logfile.
*/
void StartLog(const std::string &outDir);
/**
* Log output to an existing stream
*
* This might be std::cout/cerr or something else, e.g. a
* stringstream.
*/
void StartLog(std::ostream &s);
/**
* Get the output directory for the log file, or
* an empty string if not logging to a file.
*/
const std::string &GetOutputDirectory();
/**
* Stop logging.
*
* @param gzip If true and we are logging to a file, gzip the logfile
*/
void StopLog(bool gzip = false);
/**
* @return true if StartLog has been called
*/
bool LogStarted();
/**
* Get the logging stream. Easier to use the LOG macro defined above
*/
std::ostream &LogStream();
/**
* Issue a warning
*
* The warning will appear once in the log.
* If the same warning occurs again, it will not
* be repeated, apart from if ReissueWarnings is
* called
*/
void WarnOnce(const std::string &text);
/**
* Issue a warning
*
* The warning will appear in the log each time it is issued.
*/
void WarnAlways(const std::string &text);
/**
* Resend all warnings recorded so far to the log
*/
void ReissueWarnings();
private:
std::ostream *m_stream;
std::stringstream m_templog;
std::string m_outdir;
std::map<std::string, int> m_warncount;
};
class Loggable
{
public:
explicit Loggable(EasyLog *log = 0)
: m_log(log)
, m_debug(false)
{
}
EasyLog *GetLogger() const
{
return m_log;
}
void SetLogger(EasyLog *log)
{
m_log = log;
}
protected:
EasyLog *m_log;
bool m_debug;
};
/**
* Convert almost anything to a string
*/
template <typename type> inline std::string stringify(type from)
{
std::ostringstream s;
if (!(s << from))
throw std::logic_error("Stringify failed");
return s.str();
}
/**
* Output a vector<int>
*/
inline std::ostream &operator<<(std::ostream &out, std::vector<int> x)
{
out << "[ ";
for (unsigned i = 0; i < x.size(); i++)
out << x[i] << " ";
out << "]";
return out;
}