1 /* Copyright Jukka Jyl�nki
2
3    Licensed under the Apache License, Version 2.0 (the "License");
4    you may not use this file except in compliance with the License.
5    You may obtain a copy of the License at
6
7        http://www.apache.org/licenses/LICENSE-2.0
8
9    Unless required by applicable law or agreed to in writing, software
10    distributed under the License is distributed on an "AS IS" BASIS,
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    See the License for the specific language governing permissions and
13    limitations under the License. */
14
15 /** @file Log.h
16         @author Jukka Jyl�nki
17         @brief The LOG and LOGUSER macros. Provides an unified mechanism for logging. */
18 #pragma once
19
20 #include "Math/MathNamespace.h"
21
22 #include <stdio.h>
23
24 #if defined(ANDROID)
25 /// This will require you to pass '-llog' on the command line to link against the Android logging libraries.
26 #include <android/log.h>
27 #endif
28
29 #ifdef WIN8PHONE
30 #ifndef NOMINMAX
31 #define NOMINMAX
32 #endif
33 #include <Windows.h>
34 #endif
35
36 MATH_BEGIN_NAMESPACE
37
38 // From http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/
39 #ifdef _MSC_VER
40 #define MULTI_LINE_MACRO_BEGIN do { \
41         __pragma(warning(push)) \
42         __pragma(warning(disable:4127))
43
44 #define MULTI_LINE_MACRO_END \
45         } while(0) \
46         __pragma(warning(pop))
47
48 #else
49
50 #define MULTI_LINE_MACRO_BEGIN do {
51 #define MULTI_LINE_MACRO_END } while(0)
52
53 #endif
54
55 /// A bitfield type that describes single or multiple log channels (each bit represents a channel).
56 typedef unsigned int LogChannel;
57
58 namespace
59 {
60 const LogChannel LogUser = 1;        ///< This log channel is free to use for user-level application messages.
61 const LogChannel LogInfo = 2;        ///< Successful connects and disconnects.
62 const LogChannel LogError = 4;       ///< All connection-related errors.
63 const LogChannel LogWarning = 8;       ///< All connection-related errors.
64 const LogChannel LogObjectAlloc = 16; ///< For debugging: prints information about object allocations an deallocations.
65 const LogChannel LogData = 32;       ///< For debugging: dumps information about in- and outbound packet data.
66 const LogChannel LogVerbose = 64;    ///< For debugging: Print detailed internal information.
67 const LogChannel LogWaits = 128;      ///< Logs all long performance-related waits (thread/mutex blocks) that occur in the system.
68 }
69
70 /// Prints a variadic line to log.
71 /// @param logChannel The log channel to print to. This variable must have exactly one bit set, and is ANDed against
72 ///                   the currently active channels that can be set with a call to kNet::SetLogChannels.
73 /// @param filename The C++ file from which the log message occurs, pass in __FILE__.
74 /// @param lineNumber Pass in __LINE__.
75 /// @param msg The printf-style message format specifier for the text to print.
76 void TimeOutputDebugStringVariadic(LogChannel logChannel, const char *filename, int lineNumber, const char *msg, ...);
77
78 /// Prints a message to the log. Same as kNet::TimeOutputDebugStringVariadic, but does not use printf formatting.
79 void TimeOutputDebugString(LogChannel logChannel, const char *filename, int lineNumber, const char *msg);
80
81 /// Sets the currently enabled log channels. Pass in a bitwise OR of the log channels you want to enable.
82 /// If you pass in 0, all logging is disabled. By default, only the channel LogChannelUser is enabled.
83 void SetLogChannels(LogChannel logChannel);
84
85 /// Returns the currently active log channels.
86 LogChannel GetLogChannels();
87
88 /// Returns true if the specified log channel is not suppressed.
89 //bool IsLogChannelActive(LogChannel channel);
90
91 /// Sets the output for log messages. By default all logging is output to std::cout. Setting a log file
92 /// redirects all logging to that file. Calling this function with a null filename pointer restores
93 /// logging to target std::cout.
94 void SetLogFile(const char *filename);
95
96 /// When called, sets the runtime to print out all memory leaks at program exit time. Win32-only. On
97 /// linux, this is a no-op.
98 void EnableMemoryLeakLoggingAtExit();
99
100 enum ConsoleTextColor
101 {
102         ColorRed = 4, // == FOREGROUND_RED in WinCon.h
103         ColorGreen  = 2, // == FOREGROUND_GREEN in WinCon.h
104         ColorBlue = 1, // == FOREGROUND_BLUE in WinCon.h
105         ColorIntensity = 8 // == FOREGROUND_INTENSITY in WinCon.h
106 };
107
108 /// Specifies a new print color for stdout. Only works on Win32, other platforms are no-op implementations.
109 void SetStdoutTextColor(int newColor);
110
111 /// Prints out a variadic message to the log channel User.
112 #define LOGUSER(msg, ...) ( /*IsLogChannelActive(LogUser) &&*/ (TimeOutputDebugStringVariadic(LogUser, __FILE__, __LINE__, msg, ##__VA_ARGS__), true) )
113
114 #define STRINGIZE_HELPER(x) #x
115 #define STRINGIZE(x) STRINGIZE_HELPER(x)
116 #define WARNING(desc) message(__FILE__ "(" STRINGIZE(__LINE__) ") : warning: " #desc)
117
118 #if defined(NPAPI) && !defined(LOGGING_SUPPORT_DISABLED)
119 ///\todo Temporary. Implement logmsg as variadic directly instead of this kind of #define workaround.
120 void logmsg(const char *msg);
121
122 #define LOGI(...) \
123         MULTI_LINE_MACRO_BEGIN \
124                 char str____[16384]; \
125                 sprintf(str____, __VA_ARGS__); \
126                 logmsg(str____); \
127                 logmsg("\n"); \
128         MULTI_LINE_MACRO_END
129
130 #define LOGW(...) \
131         MULTI_LINE_MACRO_BEGIN \
132                 char str____[16384]; \
133                 logmsg("Warning: "); \
134                 sprintf(str____, __VA_ARGS__); \
135                 logmsg(str____); \
136                 logmsg("\n"); \
137         MULTI_LINE_MACRO_END
138
139 #define LOGE(...) \
140         MULTI_LINE_MACRO_BEGIN \
141                 char str____[16384]; \
142                 logmsg("Error: "); \
143                 sprintf(str____, __VA_ARGS__); \
144                 logmsg(str____); \
145                 logmsg("\n"); \
146         MULTI_LINE_MACRO_END
147
148 #define LOG(channel, ...) \
149         MULTI_LINE_MACRO_BEGIN \
150                 /*if (IsLogChannelActive(channel))*/ \
151                 { \
152                         char str____[16384]; \
153                         logmsg(#channel); \
154                         sprintf(str____, __VA_ARGS__); \
155                         logmsg(str____); \
156                         logmsg("\n"); \
157                 } \
158         MULTI_LINE_MACRO_END
159
160 #elif defined(ANDROID) && !defined(LOGGING_SUPPORT_DISABLED)
161
162 #ifndef LOG
163 #define LOG(channel, ...) do { /*if (IsLogChannelActive(channel))*/ (void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__); } while(0)
164 #endif
165 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
166 #define LOGW(...) do { \
167         char logfunc_str[512]; \
168         sprintf(logfunc_str, __VA_ARGS__); \
169         char logfunc_str2[512]; \
170         sprintf(logfunc_str2, "Warning: %s", logfunc_str); \
171         ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", logfunc_str2)); \
172         } while(0)
173
174 #define LOGE(...) do { \
175         char logfunc_str[512]; \
176         sprintf(logfunc_str, __VA_ARGS__); \
177         char logfunc_str2[512]; \
178         sprintf(logfunc_str2, "Error: %s", logfunc_str); \
179         ((void)__android_log_print(ANDROID_LOG_ERROR, "native-activity", logfunc_str2)); \
180         } while(0)
181
182 #elif defined(WIN8PHONE) && !defined(LOGGING_SUPPORT_DISABLED)
183
184 #define LOGI(...) \
185         MULTI_LINE_MACRO_BEGIN \
186                 char str____[16384]; \
187                 sprintf(str____, __VA_ARGS__); \
188                 OutputDebugStringA(str____); \
189                 OutputDebugStringA("\r\n"); \
190         MULTI_LINE_MACRO_END
191
192 #define LOGW(...) \
193         MULTI_LINE_MACRO_BEGIN \
194                 char str____[16384]; \
195                 OutputDebugStringA("Warning: "); \
196                 sprintf(str____, __VA_ARGS__); \
197                 OutputDebugStringA(str____); \
198                 OutputDebugStringA("\r\n"); \
199         MULTI_LINE_MACRO_END
200
201 #define LOGE(...) \
202         MULTI_LINE_MACRO_BEGIN \
203                 char str____[16384]; \
204                 OutputDebugStringA("Error: "); \
205                 sprintf(str____, __VA_ARGS__); \
206                 OutputDebugStringA(str____); \
207                 OutputDebugStringA("\r\n"); \
208         MULTI_LINE_MACRO_END
209
210 #define LOG(channel, ...) \
211         MULTI_LINE_MACRO_BEGIN \
212                 /*if (IsLogChannelActive(channel))*/ \
213                 { \
214                         char str____[16384]; \
215                         OutputDebugStringA(#channel); \
216                         sprintf(str____, __VA_ARGS__); \
217                         OutputDebugStringA(str____); \
218                         OutputDebugStringA("\r\n"); \
219                 } \
220         MULTI_LINE_MACRO_END
221
222 #elif defined(WIN32) && !defined(LOGGING_SUPPORT_DISABLED)
223
224 #ifndef LOG
225 #define LOG(channel, ...) \
226         MULTI_LINE_MACRO_BEGIN \
227                 printf(__VA_ARGS__); \
228                 printf("\n"); \
229         MULTI_LINE_MACRO_END
230 #endif
231
232 #define LOGI(...) \
233         MULTI_LINE_MACRO_BEGIN \
234                 printf(__VA_ARGS__); \
235                 printf("\n"); \
236         MULTI_LINE_MACRO_END
237
238 #define LOGW(...) \
239         MULTI_LINE_MACRO_BEGIN \
240                 SetStdoutTextColor(ColorRed | ColorGreen | ColorIntensity); \
241                 printf("Warning: "); printf(__VA_ARGS__); printf("\n"); \
242                 SetStdoutTextColor(ColorRed | ColorGreen | ColorBlue); \
243         MULTI_LINE_MACRO_END
244
245 #define LOGE(...) \
246         MULTI_LINE_MACRO_BEGIN \
247                 SetStdoutTextColor(ColorRed | ColorIntensity); \
248                 printf("Error: "); printf(__VA_ARGS__); printf("\n"); \
249                 SetStdoutTextColor(ColorRed | ColorGreen | ColorBlue); \
250         MULTI_LINE_MACRO_END
251
252 #elif (defined(PEPPER) || defined(__APPLE__) || defined(__GNUC__) || defined(EMSCRIPTEN) || defined(__FLASHPLAYER__)) && !defined(LOGGING_SUPPORT_DISABLED)
253
254 /// Prints out a variadic message to the given log channel.
255 //#define LOG(channel, msg, ...)  ( IsLogChannelActive(channel) && (TimeOutputDebugStringVariadic(channel, __FILE__, __LINE__, msg, ##__VA_ARGS__), true) )
256 #define LOG(channel, ...) do { printf(__VA_ARGS__); printf("\n"); } while(0)
257 #define LOGI(...) do { printf(__VA_ARGS__); printf("\n"); } while(0)
258 #define LOGW(...) do { printf("Warning: "); printf(__VA_ARGS__); printf("\n"); } while(0)
259 #define LOGE(...) do { printf("Error: "); printf(__VA_ARGS__); printf("\n"); } while(0)
260 /*
261 #define LOGE(msg, ...)  ( kNet::IsLogChannelActive(LogError) && (kNet::TimeOutputDebugStringVariadic(LogError, __FILE__, __LINE__, msg, ##__VA_ARGS__), true) )
262 #define LOGW(msg, ...)  ( kNet::IsLogChannelActive(LogWarning) && (kNet::TimeOutputDebugStringVariadic(LogWarning, __FILE__, __LINE__, msg, ##__VA_ARGS__), true) )
263 #define LOGI(msg, ...)  ( kNet::IsLogChannelActive(LogInfo) && (kNet::TimeOutputDebugStringVariadic(LogInfo, __FILE__, __LINE__, msg, ##__VA_ARGS__), true) )
264 */
265
266 #elif defined(LOGGING_SUPPORT_DISABLED)
267
268 /// If kNet logging is disabled, LOG() macro is a no-op. This avoids having to evaluate the arguments of the
269 /// LOG() call, which improves performance.
270 #define LOG(...) ((void)0)
271 #define LOGE(...) ((void)0)
272 #define LOGW(...) ((void)0)
273 #define LOGI(...) ((void)0)
274
275 #else
276
277 #error LOG/LOGE/LOGW/LOGI not implemented!
278 #endif
279
280 #ifdef GFXAPI_TRACE_ENABLED
281 #define TRACE LOGI
282 #else
283 #define TRACE(...) ((void)0)
284 #endif
285
286 MATH_END_NAMESPACE

Go back to previous page