Branch data Line data Source code
1 : : /*
2 : : MIT License
3 : :
4 : : Copyright (c) 2010-2020 Stephane Cuillerdier (aka Aiekick)
5 : :
6 : : Permission is hereby granted, free of charge, to any person obtaining a copy
7 : : of this software and associated documentation files (the "Software"), to deal
8 : : in the Software without restriction, including without limitation the rights
9 : : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 : : copies of the Software, and to permit persons to whom the Software is
11 : : furnished to do so, subject to the following conditions:
12 : :
13 : : The above copyright notice and this permission notice shall be included in all
14 : : copies or substantial portions of the Software.
15 : :
16 : : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 : : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 : : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 : : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 : : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 : : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 : : SOFTWARE.
23 : : */
24 : :
25 : : // ezLog is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
26 : : // ezLog is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
27 : :
28 : : #pragma once
29 : : #pragma warning(disable : 4251)
30 : :
31 : : #ifndef EZ_TOOLS_LOG
32 : : #define EZ_TOOLS_LOG
33 : : #endif // EZ_TOOLS_LOG
34 : :
35 : : #ifndef EZ_LOG_APP_NAME
36 : : #define EZ_LOG_APP_NAME "App"
37 : : #endif
38 : :
39 : : #include "ezStr.hpp"
40 : : #include "ezTime.hpp"
41 : :
42 : : /* WARNING
43 : : * FOR USING THE OLD BEAHVIOR SINGLETON
44 : : * YOU MUST DO : #define LEGACY_SINGLETON
45 : : */
46 : :
47 : : #ifdef USE_GLFW3
48 : : #include <GLFW/glfw3.h>
49 : : #elif defined(USE_SDL2)
50 : : #include <SDL.h>
51 : : #endif
52 : : #if defined(TRACY_ENABLE) && defined(LOG_TRACY_MESSAGES)
53 : : #include <tracy/Tracy.hpp>
54 : : #endif
55 : :
56 : : #ifdef _MSC_VER
57 : : #include <Windows.h>
58 : : #endif
59 : :
60 : : #include <cstdarg> /* va_list, va_start, va_arg, va_end */
61 : :
62 : : #include <iostream> // std::cout
63 : :
64 : : #include <mutex>
65 : : #include <string>
66 : : #include <vector>
67 : : #include <memory>
68 : : #include <cassert>
69 : : #include <fstream>
70 : : #include <stdexcept>
71 : : #include <functional>
72 : :
73 : : typedef long long int64;
74 : :
75 : : #ifdef _MSC_VER
76 : : #define __PRETTY_FUNCTION__ __FUNCSIG__
77 : : #endif
78 : :
79 : : #ifdef __ANDROID__
80 : : #include <android/log.h>
81 : : #endif
82 : :
83 : : #ifdef LEGACY_SINGLETON
84 : : #define IsVerboseMode (ez::Log::ref().isVerboseMode() == true)
85 : :
86 : : #define LogVarError(s, ...) \
87 : : ez::Log::ref().logStringByTypeWithFunction(ez::Log::LOGGING_MESSAGE_TYPE_ERROR, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
88 : :
89 : : #define LogVarWarning(s, ...) \
90 : : ez::Log::ref().logStringByTypeWithFunction(ez::Log::LOGGING_MESSAGE_TYPE_WARNING, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
91 : :
92 : : #define LogVarInfo(s, ...) \
93 : : ez::Log::ref().logStringByTypeWithFunction(ez::Log::LOGGING_MESSAGE_TYPE_INFOS, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
94 : :
95 : : #define LogVarDebugError(s, ...) \
96 : : ez::Log::ref().logStringByTypeWithFunction_Debug(ez::Log::LOGGING_MESSAGE_TYPE_ERROR, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
97 : :
98 : : #define LogVarDebugWarning(s, ...) \
99 : : ez::Log::ref().logStringByTypeWithFunction_Debug(ez::Log::LOGGING_MESSAGE_TYPE_WARNING, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
100 : :
101 : : #define LogVarDebugInfo(s, ...) \
102 : : ez::Log::ref().logStringByTypeWithFunction_Debug(ez::Log::LOGGING_MESSAGE_TYPE_INFOS, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
103 : :
104 : : #define LogVarLightError(s, ...) ez::Log::ref().logSimpleStringByType(ez::Log::LOGGING_MESSAGE_TYPE_ERROR, s, ##__VA_ARGS__)
105 : :
106 : : #define LogVarLightWarning(s, ...) ez::Log::ref().logSimpleStringByType(ez::Log::LOGGING_MESSAGE_TYPE_WARNING, s, ##__VA_ARGS__)
107 : :
108 : : #define LogVarLightInfo(s, ...) ez::Log::ref().logSimpleStringByType(ez::Log::LOGGING_MESSAGE_TYPE_INFOS, s, ##__VA_ARGS__)
109 : :
110 : : #define LogVarTag(t, s, ...) ez::Log::ref().logStringByTypeWithFunction(t, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
111 : :
112 : : #define LogVarLightTag(t, s, ...) ez::Log::ref().logSimpleStringByType(t, s, ##__VA_ARGS__)
113 : :
114 : : #define LogAssert(a, b, ...) \
115 : : if (!(a)) { \
116 : : LogVarDebugInfo(b, ##__VA_ARGS__); \
117 : : assert(a); \
118 : : }
119 : :
120 : : #ifdef USE_OPENGL
121 : : #define LogGlError() ez::Log::ref().logGLError("" /*__FILE__*/, __FUNCTION__, __LINE__, "")
122 : : #define LogGlErrorVar(var) ez::Log::ref().logGLError("" /*__FILE__*/, __FUNCTION__, __LINE__, var)
123 : : #endif
124 : : #else // LEGACY_SINGLETON#define IsVerboseMode (ez::Log::ref().isVerboseMode() == true)
125 : :
126 : 81 : #define LogVarError(s, ...) ez::Log::ref().logStringByTypeWithFunction(ez::Log::LOGGING_MESSAGE_TYPE_ERROR, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
127 : :
128 : : #define LogVarWarning(s, ...) \
129 : : ez::Log::ref().logStringByTypeWithFunction(ez::Log::LOGGING_MESSAGE_TYPE_WARNING, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
130 : :
131 : : #define LogVarInfo(s, ...) ez::Log::ref().logStringByTypeWithFunction(ez::Log::LOGGING_MESSAGE_TYPE_INFOS, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
132 : :
133 : : #define LogVarDebugError(s, ...) \
134 : : ez::Log::ref().logStringByTypeWithFunction_Debug(ez::Log::LOGGING_MESSAGE_TYPE_ERROR, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
135 : :
136 : : #define LogVarDebugWarning(s, ...) \
137 : : ez::Log::ref().logStringByTypeWithFunction_Debug(ez::Log::LOGGING_MESSAGE_TYPE_WARNING, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
138 : :
139 : : #define LogVarDebugInfo(s, ...) \
140 : : ez::Log::ref().logStringByTypeWithFunction_Debug(ez::Log::LOGGING_MESSAGE_TYPE_INFOS, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
141 : :
142 : 89 : #define LogVarLightError(s, ...) ez::Log::ref().logSimpleStringByType(ez::Log::LOGGING_MESSAGE_TYPE_ERROR, s, ##__VA_ARGS__)
143 : :
144 : : #define LogVarLightWarning(s, ...) ez::Log::ref().logSimpleStringByType(ez::Log::LOGGING_MESSAGE_TYPE_WARNING, s, ##__VA_ARGS__)
145 : :
146 : 15 : #define LogVarLightInfo(s, ...) ez::Log::ref().logSimpleStringByType(ez::Log::LOGGING_MESSAGE_TYPE_INFOS, s, ##__VA_ARGS__)
147 : :
148 : : #define LogVarTag(t, s, ...) ez::Log::ref().logStringByTypeWithFunction(t, std::string(__FUNCTION__), (int)(__LINE__), s, ##__VA_ARGS__)
149 : :
150 : : #define LogVarLightTag(t, s, ...) ez::Log::ref().logSimpleStringByType(t, s, ##__VA_ARGS__)
151 : :
152 : : #define LogAssert(a, b, ...) \
153 : : if (!(a)) { \
154 : : LogVarDebugInfo(b, ##__VA_ARGS__); \
155 : : assert(a); \
156 : : }
157 : :
158 : : #ifdef USE_OPENGL
159 : : #define LogGlError() ez::Log::ref().logGLError("" /*__FILE__*/, __FUNCTION__, __LINE__, "")
160 : : #define LogGlErrorVar(var) ez::Log::ref().logGLError("" /*__FILE__*/, __FUNCTION__, __LINE__, var)
161 : : #endif
162 : : #endif // LEGACY_SINGLETON
163 : : namespace ez {
164 : :
165 : : class Log {
166 : : public:
167 : : typedef int MessageType;
168 : : typedef std::function<void(const int& vType, const std::string& vMessage)> LogMessageFunctor;
169 : : enum MessageTypeEnum { LOGGING_MESSAGE_TYPE_INFOS = 0, LOGGING_MESSAGE_TYPE_WARNING, LOGGING_MESSAGE_TYPE_ERROR };
170 : :
171 : : protected:
172 : : std::mutex m_logger_Mutex;
173 : :
174 : : private:
175 : : static size_t constexpr sMAX_BUFFER_SIZE = 1024U * 3U;
176 : : std::ofstream m_debugLogFile;
177 : : int64 m_lastTick = 0;
178 : : bool m_reseted = false;
179 : : LogMessageFunctor m_standardLogFunction;
180 : : LogMessageFunctor m_openGLLogFunction;
181 : : std::vector<std::string> m_messages; // file, function, line, msg
182 : : bool m_consoleVerbose = false;
183 : :
184 : : public:
185 : 434 : Log() {
186 : : #if defined(TRACY_ENABLE) && defined(LOG_TRACY_MESSAGES)
187 : : ZoneScoped;
188 : : #endif
189 : 434 : }
190 : 434 : ~Log() {
191 : : #if defined(TRACY_ENABLE) && defined(LOG_TRACY_MESSAGES)
192 : : ZoneScoped;
193 : : #endif
194 : 434 : close();
195 : 434 : }
196 : 0 : void logSimpleString(const char* fmt, ...) {
197 : 0 : #if defined(TRACY_ENABLE) && defined(LOG_TRACY_MESSAGES)
198 : 0 : ZoneScoped;
199 : 0 : #endif
200 : 0 : std::unique_lock<std::mutex> lck(ez::Log::m_logger_Mutex, std::defer_lock);
201 : 0 : lck.lock();
202 : 0 : va_list args;
203 : 0 : va_start(args, fmt);
204 : 0 : m_LogString(nullptr, nullptr, nullptr, fmt, args);
205 : 0 : va_end(args);
206 : 0 : lck.unlock();
207 : 0 : }
208 : 312 : void logSimpleStringByType(const MessageType& vType, const char* fmt, ...) {
209 : : #if defined(TRACY_ENABLE) && defined(LOG_TRACY_MESSAGES)
210 : : ZoneScoped;
211 : : #endif
212 : 312 : std::unique_lock<std::mutex> lck(ez::Log::m_logger_Mutex, std::defer_lock);
213 : 312 : lck.lock();
214 : 312 : va_list args;
215 : 312 : va_start(args, fmt);
216 : 312 : m_LogString(&vType, nullptr, nullptr, fmt, args);
217 : 312 : va_end(args);
218 : 312 : lck.unlock();
219 : 312 : }
220 : 0 : void logStringWithFunction(const std::string& vFunction, const int& vLine, const char* fmt, ...) {
221 : 0 : #if defined(TRACY_ENABLE) && defined(LOG_TRACY_MESSAGES)
222 : 0 : ZoneScoped;
223 : 0 : #endif
224 : 0 : std::unique_lock<std::mutex> lck(ez::Log::m_logger_Mutex, std::defer_lock);
225 : 0 : lck.lock();
226 : 0 : va_list args;
227 : 0 : va_start(args, fmt);
228 : 0 : m_LogString(nullptr, &vFunction, &vLine, fmt, args);
229 : 0 : va_end(args);
230 : 0 : lck.unlock();
231 : 0 : }
232 : 480 : void logStringByTypeWithFunction(const MessageType& vType, const std::string& vFunction, const int& vLine, const char* fmt, ...) {
233 : : #if defined(TRACY_ENABLE) && defined(LOG_TRACY_MESSAGES)
234 : : ZoneScoped;
235 : : #endif
236 : 480 : std::unique_lock<std::mutex> lck(ez::Log::m_logger_Mutex, std::defer_lock);
237 : 480 : lck.lock();
238 : 480 : va_list args;
239 : 480 : va_start(args, fmt);
240 : 480 : m_LogString(&vType, &vFunction, &vLine, fmt, args);
241 : 480 : va_end(args);
242 : 480 : lck.unlock();
243 : 480 : }
244 : 0 : void logStringByTypeWithFunction_Debug(const MessageType& vType, const std::string& vFunction, const int& vLine, const char* fmt, ...) {
245 : 0 : #ifdef _DEBUG
246 : 0 : #if defined(TRACY_ENABLE) && defined(LOG_TRACY_MESSAGES)
247 : 0 : ZoneScoped;
248 : 0 : #endif
249 : 0 : std::unique_lock<std::mutex> lck(ez::Log::m_logger_Mutex, std::defer_lock);
250 : 0 : lck.lock();
251 : 0 : va_list args;
252 : 0 : va_start(args, fmt);
253 : 0 : m_LogString(&vType, &vFunction, &vLine, fmt, args);
254 : 0 : va_end(args);
255 : 0 : lck.unlock();
256 : 0 : #else
257 : 0 : (void)vType;
258 : 0 : (void)vFunction;
259 : 0 : (void)vLine;
260 : 0 : (void)fmt;
261 : 0 : #endif
262 : 0 : }
263 : 0 : void logStringWithFunction_Debug(const std::string& vFunction, const int& vLine, const char* fmt, ...) {
264 : 0 : #ifdef _DEBUG
265 : 0 : #if defined(TRACY_ENABLE) && defined(LOG_TRACY_MESSAGES)
266 : 0 : ZoneScoped;
267 : 0 : #endif
268 : 0 : std::unique_lock<std::mutex> lck(ez::Log::m_logger_Mutex, std::defer_lock);
269 : 0 : lck.lock();
270 : 0 : va_list args;
271 : 0 : va_start(args, fmt);
272 : 0 : m_LogString(nullptr, &vFunction, &vLine, fmt, args);
273 : 0 : va_end(args);
274 : 0 : lck.unlock();
275 : 0 : #else
276 : 0 : (void)vFunction;
277 : 0 : (void)vLine;
278 : 0 : (void)fmt;
279 : 0 : #endif
280 : 0 : }
281 : : #ifdef USE_OPENGL
282 : : bool logGLError(const std::string& vFile, const std::string& vFunc, int vLine, const std::string& vGLFunc = "") const {
283 : : (void)vFile;
284 : :
285 : : #if defined(TRACY_ENABLE) && defined(LOG_TRACY_MESSAGES)
286 : : ZoneScoped;
287 : : #endif
288 : : if (!ConsoleVerbose) {
289 : : return false;
290 : : }
291 : :
292 : : const GLenum err(glGetError());
293 : : if (err != GL_NO_ERROR) {
294 : : std::string error;
295 : :
296 : : switch (err) {
297 : : case GL_INVALID_OPERATION: error = "INVALID_OPERATION"; break;
298 : : case GL_INVALID_ENUM: error = "INVALID_ENUM"; break;
299 : : case GL_INVALID_VALUE: error = "INVALID_VALUE"; break;
300 : : case GL_OUT_OF_MEMORY: error = "OUT_OF_MEMORY"; break;
301 : : case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break;
302 : : case GL_STACK_UNDERFLOW: error = "GL_STACK_UNDERFLOW"; break;
303 : : case GL_STACK_OVERFLOW: error = "GL_STACK_OVERFLOW"; break;
304 : : }
305 : :
306 : : if (!error.empty()) {
307 : : const int64 ticks = ez::time::GetTicks();
308 : : const float time = (ticks - m_lastTick) / 1000.0f;
309 : :
310 : : std::string msg;
311 : :
312 : : if (!vGLFunc.empty()) {
313 : : #ifdef USE_GLFW3
314 : : msg = str::toStr(
315 : : "[%010.3fs][GLFW3 0x%X][%s:%i] %s in %s\n", time, (uintptr_t)glfwGetCurrentContext(), vFunc.c_str(), vLine, error.c_str(), vGLFunc.c_str());
316 : : #elif defined(USE_SDL2)
317 : : msg = str::toStr(
318 : : "[%010.3fs][SDL2 0x%X][%s:%i] %s in %s\n", time, (uintptr_t)SDL_GL_GetCurrentContext(), vFunc.c_str(), vLine, error.c_str(), vGLFunc.c_str());
319 : : #endif
320 : : } else {
321 : : #ifdef USE_GLFW3
322 : : msg = str::toStr("[%010.3fs][GLFW3 0x%X][%s:%i] %s\n", time, (uintptr_t)glfwGetCurrentContext(), vFunc.c_str(), vLine, error.c_str());
323 : : #elif defined(USE_SDL2)
324 : : msg = str::toStr("[%010.3fs][SDL2 0x%X][%s:%i] %s\n", time, (uintptr_t)SDL_GL_GetCurrentContext(), vFunc.c_str(), vLine, error.c_str());
325 : : #endif
326 : : }
327 : :
328 : : LogVarLightError("%s", msg.c_str());
329 : :
330 : : if (m_openGLLogFunction != nullptr) {
331 : : auto arr = str::splitStringToVector(msg, '\n');
332 : : if (arr.size() == 1U) {
333 : : m_openGLLogFunction(2, msg);
334 : : } else {
335 : : for (auto m : arr) {
336 : : m_openGLLogFunction(2, m);
337 : : }
338 : : }
339 : : }
340 : :
341 : : if (!m_debugLogFile.bad()) {
342 : : m_debugLogFile << msg << std::endl;
343 : : }
344 : :
345 : : return true;
346 : : }
347 : : }
348 : :
349 : : return false;
350 : : }
351 : : #endif
352 : 434 : void close() {
353 : : #if defined(TRACY_ENABLE) && defined(LOG_TRACY_MESSAGES)
354 : : ZoneScoped;
355 : : #endif
356 : 434 : std::unique_lock<std::mutex> lck(ez::Log::m_logger_Mutex, std::defer_lock);
357 : 434 : lck.lock();
358 : 434 : m_debugLogFile.close();
359 : 434 : m_debugLogFile.clear();
360 : 434 : lck.unlock();
361 : 434 : }
362 : :
363 : 0 : std::string getLastErrorAsString() {
364 : 0 : std::string msg;
365 : 0 :
366 : 0 : #ifdef _MSC_VER
367 : 0 : // Get the error message, if any.
368 : 0 : const DWORD errorMessageID = ::GetLastError();
369 : 0 : if (errorMessageID == 0 || errorMessageID == 6) {
370 : 0 : return std::string(); // No error message has been recorded
371 : 0 : }
372 : 0 :
373 : 0 : LPSTR messageBuffer = nullptr;
374 : 0 : const size_t size = FormatMessageA(
375 : 0 : FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
376 : 0 : nullptr,
377 : 0 : errorMessageID,
378 : 0 : MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
379 : 0 : (LPSTR)&messageBuffer,
380 : 0 : 0,
381 : 0 : nullptr);
382 : 0 :
383 : 0 : msg = std::string(messageBuffer, size);
384 : 0 :
385 : 0 : // Free the buffer.
386 : 0 : LocalFree(messageBuffer);
387 : 0 : #else
388 : 0 : // cAssert(0, "to implement");
389 : 0 : #endif
390 : 0 : return msg;
391 : 0 : }
392 : :
393 : 0 : void setStandardLogMessageFunctor(const LogMessageFunctor& vMessageLogFunctor) { m_standardLogFunction = vMessageLogFunctor; }
394 : 0 : void setOpenglLogMessageFunctor(const LogMessageFunctor& vMessageLogFunctor) { m_openGLLogFunction = vMessageLogFunctor; }
395 : :
396 : 0 : void setVerboseMode(bool vFlag) { m_consoleVerbose = vFlag; }
397 : 0 : bool isVerboseMode() { return m_consoleVerbose; }
398 : :
399 : : private:
400 : 0 : void m_createFileOnDisk() {
401 : 0 : if (m_reseted) {
402 : 0 : return;
403 : 0 : }
404 : 0 : #if defined(TRACY_ENABLE) && defined(LOG_TRACY_MESSAGES)
405 : 0 : ZoneScoped;
406 : 0 : #endif
407 : 0 : std::unique_lock<std::mutex> lck(ez::Log::m_logger_Mutex, std::defer_lock);
408 : 0 : lck.lock();
409 : 0 : m_debugLogFile.open("debug.log", std::ios::out);
410 : 0 : m_lastTick = time::getTicks();
411 : 0 : m_consoleVerbose = false;
412 : 0 : m_reseted = true;
413 : 0 : lck.unlock();
414 : 0 : }
415 : :
416 : : private:
417 : 1211 : void m_LogString(const MessageType* vType, const std::string* vFunction, const int* vLine, const char* vStr) {
418 : 1211 : const int64 ticks = time::getTicks();
419 : 1211 : const double time = (ticks - m_lastTick) / 1000.0;
420 : 0 :
421 : 1211 : static char TempBufferBis[sMAX_BUFFER_SIZE + 1];
422 : 1211 : int w = 0;
423 [ + + ][ + - ]: 1211 : if (vFunction && vLine) {
424 : 483 : w = snprintf(TempBufferBis, sMAX_BUFFER_SIZE, "[%010.3fs][%s:%i] %s", time, vFunction->c_str(), *vLine, vStr);
425 : 728 : } else {
426 : 728 : w = snprintf(TempBufferBis, sMAX_BUFFER_SIZE, "[%010.3fs] %s", time, vStr);
427 : 728 : }
428 [ + - ]: 1211 : if (w) {
429 : 1211 : const std::string msg = std::string(TempBufferBis, (size_t)w);
430 : 0 :
431 : 1211 : m_messages.push_back(msg);
432 : 0 :
433 : 0 : #if defined(TRACY_ENABLE) && defined(LOG_TRACY_MESSAGES)
434 : 0 : TracyMessageL(m_messages[m_messages.size() - 1U].c_str());
435 : 0 : #endif
436 : 0 :
437 : 0 : #ifdef __ANDROID__
438 : 0 : if (*vType == MessageTypeEnum::LOGGING_MESSAGE_TYPE_INFOS) {
439 : 0 : __android_log_write(ANDROID_LOG_INFO, EZ_LOG_APP_NAME, msg.c_str());
440 : 0 : } else if (*vType == MessageTypeEnum::LOGGING_MESSAGE_TYPE_WARNING) {
441 : 0 : __android_log_write(ANDROID_LOG_WARN, EZ_LOG_APP_NAME, msg.c_str());
442 : 0 : } else if (*vType == MessageTypeEnum::LOGGING_MESSAGE_TYPE_ERROR) {
443 : 0 : __android_log_write(ANDROID_LOG_ERROR, EZ_LOG_APP_NAME, msg.c_str());
444 : 0 : }
445 : 0 : #else
446 : 1211 : std::cout << msg << std::endl;
447 : 1211 : #endif
448 : 0 :
449 [ + - ][ - + ]: 1211 : if (vStr && m_standardLogFunction) {
450 : 0 : int type = 0;
451 : 0 :
452 [ # # ]: 0 : if (vType) {
453 : 0 : type = (int)(*vType);
454 : 0 : }
455 : 0 :
456 : 0 : auto arr = str::splitStringToVector(msg, '\n');
457 [ # # ]: 0 : if (arr.size() == 1U) {
458 : 0 : m_standardLogFunction(type, msg);
459 : 0 : } else {
460 [ # # ]: 0 : for (auto m : arr) {
461 : 0 : m_standardLogFunction(type, m);
462 : 0 : }
463 : 0 : }
464 : 0 : }
465 : 0 :
466 [ + + ]: 1211 : if (!m_debugLogFile.bad()) {
467 : 406 : m_debugLogFile << msg << std::endl;
468 : 406 : }
469 : 1211 : }
470 : 1211 : }
471 : 1288 : void m_LogString(const MessageType* vType, const std::string* vFunction, const int* vLine, const char* fmt, va_list vArgs) {
472 : 1288 : static char TempBuffer[sMAX_BUFFER_SIZE + 1];
473 : 1288 : int w = vsnprintf(TempBuffer, sMAX_BUFFER_SIZE, fmt, vArgs);
474 [ + + ]: 1288 : if (w) {
475 : 1211 : m_LogString(vType, vFunction, vLine, TempBuffer);
476 : 1211 : }
477 : 1288 : }
478 : :
479 : : public:
480 : : // old behavior
481 : : #ifdef LEGACY_SINGLETON
482 : : static Log* Instance(Log* vCopyPtr = nullptr, bool vForce = false) {
483 : : static auto instance_ptr = std::unique_ptr<Log>(new Log()); // std::make_unique is not available in cpp11
484 : : static ez::Log* _instance_copy = nullptr;
485 : : if (vCopyPtr || vForce) {
486 : : _instance_copy = vCopyPtr;
487 : : } else if (_instance_copy == nullptr) {
488 : : instance_ptr->m_createFileOnDisk();
489 : : }
490 : : if (_instance_copy) {
491 : : return _instance_copy;
492 : : }
493 : : return instance_ptr.get();
494 : : }
495 : : #else // LEGACY_SINGLETON
496 : 1288 : static std::unique_ptr<Log>& initSingleton() {
497 : 1288 : static auto mp_instance = std::unique_ptr<Log>(new Log());
498 : 1288 : return mp_instance;
499 : 1288 : }
500 : 1288 : static Log& ref() { return *initSingleton().get(); }
501 : 0 : static void unitSingleton() { initSingleton().reset(); }
502 : : #endif // LEGACY_SINGLETON
503 : : };
504 : :
505 : : } // namespace ez
|