-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlog.hpp
130 lines (106 loc) · 3.36 KB
/
log.hpp
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
#pragma once
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <utility>
#include <string_view>
#include <boost/optional.hpp>
class Logger
{
public:
Logger() = default;
/**
* @param filename The file name of the log(s) WITHOUT extension.
* @param rotation The amount of log files to keeep. Pass 0 to disable log.
*/
void open(std::string const& filename, int rotation);
/**
* Enable / Disable outputing to terminal.
*/
void setTerminalEnabled(bool enabled);
/**
* Write a stamp with time, file, function, line.
*/
void stamp(char const* file, char const* func, int line);
/**
* Logs do save their path to the file, which may become quite long.
* Use this to to remove everything from the path that is indicated by the main.cpp file. No source file
* should be above main.cpp or cutting is not performed.
*/
void configureProjectMainFile(std::string const& directory);
/**
* Also output to terminal?
*/
bool terminalEnabled();
template <typename T>
void write(T const& value)
{
if (file_.is_open())
file_ << value << std::flush;
if (terminal_)
std::cout << value;
}
void manipulate(std::ios_base&(*manip)(std::ios_base&));
private:
std::ofstream file_;
std::string root_;
bool terminal_ = true;
};
class LogProxy
{
public:
Logger& log();
/**
* Do not print endline anymore.
**/
void disable();
LogProxy() = default;
~LogProxy();
LogProxy& operator=(LogProxy const&) = delete;
LogProxy(LogProxy const&) = delete;
LogProxy(LogProxy&&) = default;
LogProxy& operator=(LogProxy&&) = default;
private:
bool disabled_;
};
LogProxy&& operator<<(LogProxy&& proxy, std::string const& value);
LogProxy&& operator<<(LogProxy&& proxy, std::string_view const& value);
LogProxy&& operator<<(LogProxy&& proxy, char value);
LogProxy&& operator<<(LogProxy&& proxy, char const* value);
LogProxy&& operator<<(LogProxy&& proxy, std::ios_base&(*manip)(std::ios_base&));
LogProxy&& operator<<(LogProxy&& proxy, std::_Setw);
template <
typename T,
class = typename std::enable_if<
(std::is_arithmetic<T>::value && !std::is_same<T, char>::value && !std::is_same<T, wchar_t>::value) &&
!std::is_enum<T>::value
>::type
>
LogProxy&& operator<<(LogProxy&& proxy, T value)
{
proxy.log().write(value);
return std::move(proxy);
}
template <typename T>
LogProxy&& operator<<(LogProxy&& proxy, boost::optional <T> const& opt)
{
if (opt)
return operator<<(std::move(proxy), opt.get());
else
return operator<<(std::move(proxy), "[nullopt]");
}
LogProxy logImpl(char const* file, char const* func, int line, bool stamp = true);
void setLogTerminalEnabled(bool enabled);
#ifndef NO_LOG_FILE
# ifdef __GNUC__
# define LOG() logImpl(__FILE__, __PRETTY_FUNCTION__, __LINE__, true)
# define LOGEX(stamp) logImpl(__FILE__, __PRETTY_FUNCTION__, __LINE__, stamp)
# else
# define LOG() logImpl(__FILE__, __func__, __LINE__, true)
# define LOGEX(stamp) logImpl(__FILE__, __func__, __LINE__, stamp)
# endif
#else
# define LOG() std::cout
# define LOGEX(X) std::cout
#endif