-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMLog.h
353 lines (301 loc) · 7.99 KB
/
MLog.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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
// MLog.h --- A simple logging library for C++/Win32 by katahiromz
// License: MIT
#pragma once
#define MLOG_VERSION 2
// Option: MLOG_MAX_BUF: 1024
// Option: MLOG_CODEPAGE: CP_UTF8
// Option: MLOG_USE_STRSAFE: (undefined)
// Option: MLOG_DEBUG_OUTPUT: (undefined)
// Option: MLOG_CONSOLE_OUTPUT: (undefined)
// Option: MLOG_FILE_OUTPUT: (undefined)
// Option: MLOG_UTF16_OUTPUT: (undefined)
// Option: MLOG_REGKEY: (undefined)
//////////////////////////////////////////////////////////////////////////////
#ifndef MLOG_MAX_BUF
#define MLOG_MAX_BUF 1024
#endif
#ifndef MLOG_CODEPAGE
#define MLOG_CODEPAGE CP_UTF8
#endif
#if !defined(MLOG_FILE_OUTPUT) && !defined(MLOG_CONSOLE_OUTPUT) && !defined(MLOG_DEBUG_OUTPUT)
#define MLOG_CONSOLE_OUTPUT
#endif
//////////////////////////////////////////////////////////////////////////////
#ifndef _INC_WINDOWS
#include <windows.h>
#endif
#ifndef _INC_TCHAR
#include <tchar.h>
#endif
#ifdef __cplusplus
#include <cstdio>
#else
#include <stdio.h>
#endif
#ifdef MLOG_USE_STRSAFE
#include <strsafe.h>
#endif
//////////////////////////////////////////////////////////////////////////////
C_ASSERT(MLOG_MAX_BUF >= MAX_PATH);
#ifdef MLOG_DEBUG_OUTPUT
#undef MLOG_UTF16_OUTPUT
#undef MLOG_CONSOLE_OUTPUT
#endif
#ifdef MLOG_CONSOLE_OUTPUT
#undef MLOG_UTF16_OUTPUT
#endif
#if defined(UNICODE) != defined(_UNICODE)
#error Macro UNICODE and _UNICODE are mismatching.
#endif
//////////////////////////////////////////////////////////////////////////////
typedef struct MLOG
{
BOOL bInit;
CRITICAL_SECTION csLock;
TCHAR log_filename[MAX_PATH];
BOOL bEnabled;
#ifdef __cplusplus
MLOG()
{
bInit = FALSE;
log_filename[0] = 0;
}
~MLOG()
{
if (!bInit)
return;
DeleteCriticalSection(&csLock);
bInit = FALSE;
}
#endif
} MLOG, *PMLOG;
//////////////////////////////////////////////////////////////////////////////
// mlog_...
static inline
PMLOG mlog_init(void)
{
#ifdef __cplusplus
static MLOG s_mlog;
#else
static MLOG s_mlog = { FALSE };
#endif
if (s_mlog.bInit)
return &s_mlog;
InitializeCriticalSection(&s_mlog.csLock);
#ifdef MLOG_DEBUG_OUTPUT
ExpandEnvironmentStrings(TEXT(""), s_mlog.log_filename, _countof(s_mlog.log_filename));
#elif defined(MLOG_CONSOLE_OUTPUT)
ExpandEnvironmentStrings(TEXT("con"), s_mlog.log_filename, _countof(s_mlog.log_filename));
#else
ExpandEnvironmentStrings(MLOG_FILE_OUTPUT, s_mlog.log_filename, _countof(s_mlog.log_filename));
#endif
s_mlog.bEnabled = TRUE;
s_mlog.bInit = TRUE;
return &s_mlog;
}
static inline
void mlog_free(void)
{
PMLOG pmlog = mlog_init();
if (!pmlog->bInit)
return;
DeleteCriticalSection(&pmlog->csLock);
pmlog->bInit = FALSE;
}
static inline
void mlog_enable(BOOL bEnabled)
{
PMLOG pmlog = mlog_init();
if (pmlog)
pmlog->bEnabled = bEnabled;
}
static inline
void mlog_lock(PMLOG pmlog)
{
EnterCriticalSection(&pmlog->csLock);
}
static inline
void mlog_unlock(PMLOG pmlog)
{
LeaveCriticalSection(&pmlog->csLock);
}
static inline
LPCTSTR mlog_log_file(void)
{
PMLOG pmlog = mlog_init();
if (!pmlog)
return NULL;
return pmlog->log_filename;
}
static inline
BOOL mlog_is_enabled(void)
{
PMLOG pmlog = mlog_init();
if (!pmlog)
return FALSE;
if (!pmlog->bEnabled)
return FALSE;
#ifdef MLOG_REGKEY
{
HKEY hKey;
#ifdef MLOG_OPTIN_LOGGING
DWORD bEnabled = FALSE;
LONG error = RegOpenKeyEx(HKEY_CURRENT_USER, MLOG_REGKEY, 0, KEY_READ, &hKey);
if (!error)
{
DWORD cbValue = sizeof(bEnabled);
RegQueryValueEx(hKey, TEXT("EnableLogging"), NULL, NULL,
(BYTE*)&bEnabled, &cbValue);
RegCloseKey(hKey);
}
if (!bEnabled)
return FALSE;
#else
DWORD bDisabled = FALSE;
LONG error = RegOpenKeyEx(HKEY_CURRENT_USER, MLOG_REGKEY, 0, KEY_READ, &hKey);
if (!error)
{
DWORD cbValue = sizeof(bDisabled);
RegQueryValueEx(hKey, TEXT("DisableLogging"), NULL, NULL,
(BYTE*)&bDisabled, &cbValue);
RegCloseKey(hKey);
}
if (bDisabled)
return FALSE;
#endif
}
#endif
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
// mlog_write...
static inline
void mlog_write_a(PMLOG pmlog, const char *ptr)
{
FILE *fout;
#ifdef MLOG_UTF16_OUTPUT
WCHAR buf[MLOG_MAX_BUF];
#endif
#ifdef MLOG_DEBUG_OUTPUT
OutputDebugStringA(ptr);
return;
#elif defined(MLOG_CONSOLE_OUTPUT)
fout = stdout;
#elif defined(MLOG_UTF16_OUTPUT)
fout = _tfopen(pmlog->log_filename, _T("ab"));
#else
fout = _tfopen(pmlog->log_filename, _T("a"));
#endif
if (!fout)
return;
#ifdef MLOG_UTF16_OUTPUT
MultiByteToWideChar(MLOG_CODEPAGE, 0, ptr, -1, buf, _countof(buf));
buf[_countof(buf) - 1] = 0;
fwrite(buf, lstrlenW(buf) * sizeof(WCHAR), 1, fout);
#else
fputs(ptr, fout);
#endif
if (fout != stdout)
fclose(fout);
}
static inline
void mlog_write_w(PMLOG pmlog, const WCHAR *ptr)
{
FILE *fout;
#ifndef MLOG_UTF16_OUTPUT
CHAR buf[MLOG_MAX_BUF];
#endif
#ifdef MLOG_DEBUG_OUTPUT
OutputDebugStringW(ptr);
return;
#elif defined(MLOG_CONSOLE_OUTPUT)
fout = stdout;
#elif defined(MLOG_UTF16_OUTPUT)
fout = _tfopen(pmlog->log_filename, _T("ab"));
#else
fout = _tfopen(pmlog->log_filename, _T("a"));
#endif
if (!fout)
return;
#ifndef MLOG_UTF16_OUTPUT
WideCharToMultiByte(MLOG_CODEPAGE, 0, ptr, -1, buf, _countof(buf), NULL, NULL);
buf[_countof(buf) - 1] = 0;
fwrite(buf, lstrlenA(buf) * sizeof(CHAR), 1, fout);
#else
fwrite(ptr, lstrlenW(ptr) * sizeof(WCHAR), 1, fout);
#endif
if (fout != stdout)
fclose(fout);
}
#ifdef UNICODE
#define mlog_write mlog_write_w
#else
#define mlog_write mlog_write_a
#endif
//////////////////////////////////////////////////////////////////////////////
// mlog_trace_ex...
static inline
void mlog_trace_ex_a(PMLOG pmlog, const char *file, int line, const char *fmt, ...)
{
CHAR buf[MLOG_MAX_BUF];
va_list va;
int cch;
va_start(va, fmt);
mlog_lock(pmlog);
if (mlog_is_enabled())
{
#ifdef MLOG_USE_STRSAFE
StringCchPrintfA(buf, _countof(buf), "%s (%d): ", file, line);
cch = lstrlenA(buf);
StringCchVPrintfA(&buf[cch], _countof(buf) - cch, fmt, va);
#else
cch = _snprintf(buf, _countof(buf), "%s (%d): ", file, line);
_vsnprintf(&buf[cch], _countof(buf) - cch, fmt, va);
#endif
mlog_write_a(pmlog, buf);
}
mlog_unlock(pmlog);
va_end(va);
}
static inline
void mlog_trace_ex_w(PMLOG pmlog, const WCHAR *file, int line, const WCHAR *fmt, ...)
{
WCHAR buf[MLOG_MAX_BUF];
va_list va;
int cch;
va_start(va, fmt);
mlog_lock(pmlog);
if (mlog_is_enabled())
{
#ifdef MLOG_USE_STRSAFE
StringCchPrintfW(buf, _countof(buf), L"%s (%d): ", file, line);
cch = lstrlenW(buf);
StringCchVPrintfW(&buf[cch], _countof(buf) - cch, fmt, va);
#else
cch = _snwprintf(buf, _countof(buf), L"%s (%d): ", file, line);
_vsnwprintf(&buf[cch], _countof(buf) - cch, fmt, va);
#endif
mlog_write_w(pmlog, buf);
}
mlog_unlock(pmlog);
va_end(va);
}
#ifdef UNICODE
#define mlog_trace_ex mlog_trace_ex_w
#else
#define mlog_trace_ex mlog_trace_ex_a
#endif
//////////////////////////////////////////////////////////////////////////////
// mlog_trace...
#define MLOG_WIDE(str) L##str
#define MLOG_WIDE_(str) MLOG_WIDE(str)
#define mlog_trace_a(fmt, ...) \
mlog_trace_ex_a(mlog_init(), __FILE__ , __LINE__, fmt, ## __VA_ARGS__)
#define mlog_trace_w(fmt, ...) \
mlog_trace_ex_w(mlog_init(), MLOG_WIDE_(__FILE__), __LINE__, fmt, ## __VA_ARGS__)
#ifdef UNICODE
#define mlog_trace mlog_trace_w
#else
#define mlog_trace mlog_trace_a
#endif
//////////////////////////////////////////////////////////////////////////////